How to use extern “C” dll function taking char** as an argument in C# application?

匿名 (未验证) 提交于 2019-12-03 00:44:02

问题:

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#?

回答1:

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 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!