I have dll with function:
extern "C" int doJob(char** buffer);
Its usage with C++ looks like this:
char* buf; int status = doJob(&buf);
What definition should I have for this function in C#? How can I use this function in C#?
I have dll with function:
extern "C" int doJob(char** buffer);
Its usage with C++ looks like this:
char* buf; int status = doJob(&buf);
What definition should I have for this function in C#? How can I use this function in C#?
One of the possible patterns is:
[DllImport("containsdojob.dll", CallingConvention = CallingConvention.Cdecl)] public static extern Int32 doJob(out IntPtr buffer); [DllImport("containsdojob.dll", CallingConvention = CallingConvention.Cdecl)] public static extern void freeMemory(IntPtr buffer);
and
IntPtr buffer = IntPtr.Zero; string str = null; try { doJob(out buffer); if (buffer != IntPtr.Zero) { str = Marshal.PtrToStringAnsi(buffer); } } finally { if (buffer != IntPtr.Zero) { freeMemory(buffer); } }
Note that you'll need a freeMemory
method to free the memory allocated by doJob
.
There are other possible patterns, for example based on BSTR
and SysAllocString
that are easier to implement C#-side (but more difficult to implement C-side)
The "pattern" for using BSTR:
C-side:
char *str = "Foo"; // your string int len = strlen(str); int wslen = MultiByteToWideChar(CP_ACP, 0, str, len, 0, 0); BSTR bstr = SysAllocStringLen(NULL, wslen); MultiByteToWideChar(CP_ACP, 0, str, len, bstr, wslen); // bstr is the returned string
C#-side:
[DllImport("containsdojob.dll", CallingConvention = CallingConvention.Cdecl)] public static extern Int32 doJob([MarshalAs(UnmanagedType.BStr)] out string buffer); string str; doJob(out str);
The memory is automatically handled (freed) by the CLR.
If you are using Visual C++ you can even
char *str = "Foo"; // your string _bstr_t bstrt(str); BSTR bstr = bstrt.Detach(); // bstr is the returned string
Or C-side you could use one of the two allocators that can be freed C#-side: LocalAlloc or CoTaskMemAlloc:
char *str = "Foo"; // your string char *buf = (char*)LocalAlloc(LMEM_FIXED, strlen(str) + 1); // or char *buf = (char*)CoTaskMemAlloc(strlen(str) + 1); strcpy(buf, str); // buf is the returned string
Then you use the first example, but instead of calling
freeMemory(buffer);
you call:
Marshal.FreeHGlobal(buffer); // for LocalAlloc
or
Marshal.FreeCoTaskMem(buffer); // for CoTaskMemAlloc