Pass C# reference to C++ pointer and back - c#

I would like to pass C# reference to C/C++ code(pointer), and than get it back from pointer to C#reference.
I have many pairs (uint,Object). I created sorting mechanism in C code, because its much faster than C#. There is only key(uint) and value(object reference) needed. C code is using key for sorting, and is not changing the value(pointer). Is there any simple way to do it? Do i need to use marshalling? C function will be called many times(maybe even a million times), so i am affraid it will be with marshalling too slow, and i don´t even know how to do it with marshalling. I believe when objects address is changed by GC, address of C# reference is not changed. So there will not be needed to place object in pined memory. Am i right about this?
Now i am able to call C function using DllImport, i am able to store C# reference to C pointer, but i am not able to get address stored in C pointer to C# reference.
Any ideas on how to do this?

It is not possible to pass any variables directly from manged c# code to native c++ code. The solution is pinvoke where you can marshal the data.
This works fine but you should know that this is not everytime the fastes solution. On every call the memory must be copied and maybe converted depending on the data types.

My solution to a similar problem, I had some old code in Fortan.
I convert this code to c, then created a managed c++ project.
In c#, I called this manged c++ project.
the c# code looks like this:
unsafe
{
double* input = (double*)utils.Memory.Alloc(sizeof(double) * n);
double* output = (double*)utils.Memory.Alloc(sizeof(double) * n);
//calling the c++ code
c_plus_plus.code(input,output);
//now output contains the output
// (you can use the same array as input and output
}
I hope this helps.

Related

C# 2D pointer array

I am currently messing around with C# in order to be able to approach ASP.NET with an acceptable knowledge base. In order to do so I occasionally look at my old C++ code and see if I can figure out how to make it work in C#.
So I figured that I will look into arrays, a pretty common way to store data. What I was wondering is what would the C# equivalent of creating a two dimensional array via pointers would look like?
I know that in C++ one way to do it could look like this:
double **myArray;
myArray = new double * [rows];
for(int I = 0; I < rows; I++) {
myArray[I] = new double[cols];
}
I also know that in C# you could easily just say double [rows,cols] and that would create a 2D array. I know that C++ and C# most likely treat pointers differently, but just for the sake of interest, how would I mimic a similar behavior in C#?
Cheers.
C# arrays and C++ pointers are incredibly similar, with the biggest difference is that C# has a layer of managed logic on top of the array data.
An array of pointers in C# is possible. You could do it, for example, with:
unsafe
{
double*[] ptrArray = new double*[5];
ptrArray[2][0] = 4.0;
double*[,] ptr2DArray = new double*[5,5];
ptr2DArray [2, 2][0] = 4.0;
}
However, like I said in my previous comment, using pointers in C# is discouraged, and generally you want to use a managed approach whenever possible. Personally, I cannot fathom a need for creating an array of pointers (much less a 2D array) and I imagine that if someone's program needs a structure like this, then they probably need to rethink their approach.
Usually pointers are very less used in C#, When you use pointers in C# it is considered as unsafe context.
Please check following MSDN Pointer Document that illustrates how to use pointers.
I would like to say don't use pointers if not required. You can use Ref Keyword and Out keyword to pass your parameter as a reference.
When you use pointer you loose all managed code benefits.
You can check C# ref is it like a pointer in C/C++.
Apart from that i think that all arrays are already Reference Type even if it contains all members of value type.
Check Value Types and Reference Types in C#.
I hope it helps.

Sending a 2D int array between C# and C++

I'm trying to create a solution where I can run a 2D int array within a C# program through CUDA, so the approach I'm currently taking to try and do this is by creating a C++ dll which can handle the CUDA code then return the 2D array. The code I'm using to send my array to the dll and back again is below.
#include "CudaDLL.h"
#include <stdexcept>
int** cudaArrayData;
void CudaDLL::InitialiseArray(int arrayRows, int arrayCols, int** arrayData)
{
cudaArrayData = new int*[arrayCols];
for(int i = 0; i < arrayCols; i++)
{
cudaArrayData[i] = new int[arrayRows];
}
cudaArrayData = arrayData;
}
int** CudaDLL::ReturnArray()
{
return cudaArrayData;
}
The problem however is I get an error in C# on the return, "Cannot marshal 'return value': Invalid managed/unmanaged type combination." My hope was if I returned the array back as a pointer C# might have hopefully understood and accepted it however no such luck.
Any idea's?
As you’re using int[,] in C#, int** is not the right corresponding type in C++. int[][] is an array of arrays of ints, similar to int** in C++; whereas int[,] is one array of ints with 2D indexing: index = x + y * width. Using int** in C#/C++ interop is difficult, as you have many pointers to either managed or unmanaged memory, which is not directly accessible from one to another (see further down).
Already in InitialiseArray(..., int** arrayData) you read somewhere in your memory but not in array values as you don't pass an array with pointers to arrays of ints, you pass one single array of int.
When you return int** in ReturnArray(), your problem is that .net has no clue how to interpret that pointer to an pointer.
To fix this, use only int* on C++ side and don’t return the array as a function return value, this would only give you a pointer to the unmanaged array and not the entire data in managed memory. It is possible to use this from C#, but probably not in the way you intend to do. Use an array allocated in C# as function argument in void ReturnArray(int* retValues) to copy the data to.
The other problem is then data copying and memory allocations. You can avoid all of these steps if you handle memory in C# right, i.e. forbid the garbage collector to move your data around (it does that when cleaning up unused objects). Either use a fixed{} statement or do it manually via GCHandle.Alloc(array, GCHandleType.Pinned). Doing so, you can directly use the C# allocated arrays from within C++.
Finally, if all you need is to let a CUDA kernel run on your C# data, have a look at some cuda wrappers that handle all the Pinvoke hazards for you. Like managedCuda (I maintain this project) or cudafy and some others.

Marshal between C# byte array and C++ byte array

I have a C# array<System::Byte> and I want that to translate to a C++ byte*. How can I do that? I am using C++/CLR because it lets me use managed/unmanaged code in the same project. I'm basically writing a DLL and making a few methods that can be called via C#, but that contain unmanaged C++ code.
So basically, my C++/CLR method header is this:
void testMethod(array<Byte>^ bytesFromCSharp);
and inside of that testMethod I would like to translate the bytesFromCSharp into a byte* which can be used by other unmanaged C++ code. I malloced the byte* array and wrote a for loop to copy byte by byte but it feels like there should be a better solution.
edit: Example of Hans' technique from his answer below:
//C#
byte[] myBytes = {1,2,3,4};
//C++/CLI
void testMethod(array<byte>^ myBytes) {
pin_ptr<byte> thePtr = &myBytes[0];
byte* bPtr = thePtr;
nativeCode(bPtr);
...
}
Use the pin_ptr<> template class to pin the array and generate a pointer that native code can use. Pinning it ensures that the array cannot be moved by the garbage collector while the native code is using it.
Just make sure that the native code cannot use the array anymore after the pin_ptr<> variable goes out of scope. Which also means that native code storing the pointer for later use is not okay. If it does then you have to make a copy.

What happens when I call a function in a DLL

I use a dll compiled from C++ code (LPSolve, see http://lpsolve.sourceforge.net/5.5/), from my C# code. I use the API to build a linear programming model, and subsequently solve it. I call functions such as:
[DllImport("lpsolve55.dll", SetLastError = true)]
public static extern bool add_columnex
(int lp, int count, double[] column, int[] rowno);
I am wondering what happens, memorywise, when I call such a function and the ints and arrays that I created in managed code leave scope (in the c# code). Will they be eligible for garbage collection? What does this mean for the c++ code? Or are the ineligible, and in that case: why?
Because the function prototype is using plain old datatypes and arrays, the memory for these values is pinned in place and then the native code acts directly on the data. Then when the function returns, the memory is unpinned and can be garbage collected.
In other words, they never leave the scope.
In terms of the C++ code, if it needs to store any of the data then it will need to take a copy of the data passed into it and then manage that memory itself.
I think Nick has covered the basic part, this is just to add more information. Array of int/double are considered as blittable types (types that have same layout in managed/unmanaged worlds) - these are typically get pinned when Marshalled. So you don't have to about GC. Also, what you have done indicates passing array by value - in such case, marshaller treats this as In parameter - in case, your unmanaged dll is going to update values in array then I would suggest you to mark it as In/Out parameter (e.g. [In, Out]double[] column). For more info:
Blittable and Non-Blittable Types:
http://msdn.microsoft.com/en-us/library/75dwhxf7.aspx
Copying and Pinning: http://msdn.microsoft.com/en-us/library/23acw07k.aspx
Marshalling Arrays: http://learning.infocollections.com/ebook%202/Computer/Programming/General/Programming.With.Microsoft.Dot.NET/LiB0948.htm
If your app doesn't crash with an AccessViolationException after using it for a while (past a garbage collection) then it is pretty safe to assume that the unmanaged code made a copy of the array elements you passed it. This is the normal thing to do, the library would otherwise be very hard to use from native code as well. There also ought to be an API function that lets you clear or re-initialize the model, that one should be releasing the memory.
The C or C++ function has a prototype like this:
bool add_columnex(int lp, int count, double[] column, int[] rowno);
The parameters lp and count are passed by value. The parameters column and rowno are also passed by value but the actual data is passed by reference, the function add_columnex will have to dereference column and rowno. This dereferentiation is only allowed during the function call. When the function returns, these parameters are out of scope. The kind of derenferentation must be in the contract of the interface.
When the function returns all arguments get out of scope and there is no mean that the function could do anything after call. If the function stores copies of the arguments, i.e. the address of the double or rowno array, this must be allowed by the contract. In that case you would get in trouble. A better contract would be that the function must copy the dereferenced data.

Interface from a C DLL to .NET

I have a legacy DLL written in C that I'd like to call from a C# .NET application. The problem is that the DLL interface for the C DLL is fairly complicated. It's something like this:
__declspec(dllexport) void __stdcall ProcessChunk(
void *p_prochdl,
const BIG_INPUT_STRC *p_inparams,
BIG_OUTPUT_STRC *p_outparams
);
The BIG_INPUT_STRC/BIG_OUTPUT_STRC contain all kinds of things... pointers to buffer arrays, enumerated parameters, integer parameters, etc. In short, they're complicated.
First question: Is there an easy way to get all of the structure information that is contained in the DLL header file into the C# class, or do you need to literally copy and paste everything to C# and re-define it? This seems redundant.
Related to that, what is the correct way to pass structs into the unmanaged DLL from C#?
Finally, is there an example of how to correctly pass buffer arrays from C# into the unmanaged DLL? Alternatively, how can I pass a two-dimensional array into the DLL?
Thanks,
-Greg
Its quite straight forward to do this soft of thing in C# using P/Invoke.
I belive you are going to have to define the data structures in C# manually.
I would reccomend you take a look at this MSDN article on the subject
You'll need to extensively use .net marshalling. First you need to re-define C structs in your C# code, then make sure everything gets marshalle properly using the MarshalAs attribute.
If you need to pass a pointer-to-structure in C# back to the C function you can use the Marshal.StructToPtr function.
Buffer arrays, assuming they're defined as byte[] you can marshal using the following technique:
byte[] buffer = ...;
fixed(byte *pBuffer = buffer)
{
// do something with the pBuffer
}
The fixed statement makes sure that the bufffer doesn't get moved in the memory by the garbage collector, making the pointer within the statement 'fixed' or 'pinned'.
As for the multi dimensional arrays, it depends on the underlying C implementation, you might for example work with a pointer to the array and adjust the position based on the number of dimension and the number of elements in each dimension like:
someValue = buffer[(elementsPerDimensions * x) + y];
From your description it already seems pretty complicated, have you considered making your library COM friendly?
What a pill.
I'd avoid trying to make the library COM friendly. That's more trouble than its worth.
I'd build a second native library with functions designed to be P/INVOKED to build up the records for the first and call it.
Alternately, you could make a C++ native/managed library to handle the marshaling.

Categories

Resources