How to match and merge a C array into C # code

I am writing C # code that calls the C library, and something is not entirely clear in my mind.

Function C has the following signature:

double* DoSomeStuff(double* input,int numberOfElements); 

I displayed the function as:

 [System.Runtime.InteropServices.DllImportAttribute("myDll.dll", EntryPoint="DoSomeStuff")] public static extern System.IntPtr DoSomeStuff(ref double input, int numberOfElements) ; 

The input value is an array, so the C function expects an adjacent memory layout. I am more familiar with C ++ than with C #. In C ++, I used std :: vector to store data, and then used the data () method to get the pointer and exchange information with C. std :: vector guarantees continuous layout memory.

What data structure can I use in C #? Is there something like std :: vector in C #?

I faced the same problem for a string (in C ++ std :: string there is only std :: vector with some make-up). And I solved the problem using:

 System.IntPtr stringExample = Marshal.StringToHGlobalAnsi("StringExample"); 

A static function does the job for me. Is there something like this function for other types?

I asked too many questions, I think the most important of them: what is the best practice to solve this problem?

thanks

+4
source share
2 answers

1)

Define the input as IntPtr:

 [System.Runtime.InteropServices.DllImportAttribute("myDll.dll", EntryPoint="DoSomeStuff")] public static extern System.IntPtr DoSomeStuff(IntPtr input, int numberOfElements) ; 

2)

Create an array in fixed , then create an IntPtr from the Pointer, and then pass it to DoSomeStuff .

 double[] input = new double[20]; IntPtr result = IntPtr.Zero; fixed(double* d = &input[0]) { result = DoSomeStuff(new InptPtr(d), 20); } ... 

The reason for the fixed block is that the GC does not move the array, and unmanaged code fills it.

+4
source

To make your work example, you must define the syntax of the extern function as follows:

 [System.Runtime.InteropServices.DllImportAttribute("myDll.dll", EntryPoint="DoSomeStuff")] public static extern System.IntPtr DoSomeStuff([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)], int numberOfElements); 

The second (named) MarshalAs attaribute parameter tells the marshaller where the size of the array is stored.

Regarding the second question, C # has a List<Type> class, which behaves similarly to std:vector<Type> . However, I do not think that you can directly provide it to the marshaller. You can use the ToArray() method of the List method to get an array.

+1
source

Source: https://habr.com/ru/post/1342631/


All Articles