PInvoke function for C that returns char *

I am trying to write C # code that calls a method from an unmanaged DLL. The prototype of the function in the dll is:

extern "C" __declspec(dllexport) char *foo(void); 

In C #, I first used:

 [DllImport(_dllLocation)] public static extern string foo(); 

It seems to work on the surface, but at runtime I get errors in memory corruption. I think that I am pointing to a memory that is correct, but already freed.

I tried using the PInvoke code utility called "P / Invoke Interop Assistant". This gave me the result:

 [System.Runtime.InteropServices.DLLImportAttribute(_dllLocation, EntryPoint = "foo")] public static extern System.IntPtr foo(); 

It is right? If so, how do I convert this IntPtr to a string in C #?

+41
c # pinvoke
Dec 15 '08 at 23:42
source share
2 answers

You should return this as IntPtr. Returning the System.String type from the PInvoke function requires great care. The CLR must transfer memory from its own view to the managed one. This is a simple and predictable operation.

The problem, however, is with what to do with the original memory that was returned from foo (). The CLR takes the following two elements about the PInvoke function, which directly returns the string type

  • It is necessary to free the internal memory.
  • Own memory was allocated by CoTaskMemAlloc

Therefore, it will marshal the string and then call CoTaskMemFree in the memory block. If you did not allocate this memory using CoTaskMemAlloc, this will at best lead to a crash in your application.

To get the correct semantics here, you must immediately return IntPtr. Then use Marshal.PtrToString * to go to the managed value of String. You can still free the internal memory, but that will depend on the implementation of foo.

+66
Dec 16 '08 at 5:18
source share

You can use the Marshal.PtrToStringAuto method.

 IntPtr ptr = foo(); string str = Marshal.PtrToStringAuto(ptr); 
+17
Dec 15 '08 at 23:46
source share



All Articles