如何在 C# 应用程序中使用 extern "C" dll 函数以 char** 作为参数?

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

本文关键字:char 函数 参数 dll 应用程序 extern      更新时间:2023-10-16

我有带功能的dll

extern "C"
int
doJob(char** buffer);

它在C++中的用法如下:

char* buf;
int status = doJob(&buf);

在C#中,我应该对这个函数有什么定义?如何在C#中使用此函数?

可能的模式之一是:

[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);

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);
    }
}

请注意,您需要一个freeMemory方法来释放doJob分配的内存。

还有其他可能的模式,例如基于BSTRSysAllocString,它们更容易实现C#端(但更难实现C端)

使用BSTR:的"模式"

C侧:

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#侧:

[DllImport("containsdojob.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 doJob([MarshalAs(UnmanagedType.BStr)] out string buffer);
string str;
doJob(out str);

内存由CLR自动处理(释放)。

如果你使用的是Visual C++,你甚至可以

char *str = "Foo"; // your string
_bstr_t bstrt(str);
BSTR bstr = bstrt.Detach(); 
// bstr is the returned string

或者在C端,您可以使用两个可以释放的分配器之一:LocalAlloc或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

然后使用第一个示例,但不是调用

freeMemory(buffer);

你打电话给:

Marshal.FreeHGlobal(buffer); // for LocalAlloc

Marshal.FreeCoTaskMem(buffer); // for CoTaskMemAlloc