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

标签 c# c++ c dll unmanaged

我有一个具有以下功能的 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 端,您可以使用可释放 C# 端的两个分配器之一:LocalAllocCoTaskMemAlloc :

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

关于c# - 如何在 C# 应用程序中使用 extern "C"dll 函数以 char** 作为参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29508180/

相关文章:

c# - 运算符 '&' 不能应用于类型 'T' 和 'T' 的操作数

c# - 使用Rx Start, Retry, Delay, 等待同步文件删除重试

c++ - wxWidgets 绘画自定义控件

objective-c - 在 Objective-C 中使用 C 定义

c - 免费动态分配的内存

c# - 从 Amazon AWS S3 下载对象时流仅部分读取

c# - 使用 ASP.net Identity 和 Web API 获取用户角色

c++ - Win32 - 获取应用程序的主窗口句柄

c++ - 库中的 exit() 可以用抛出异常代替吗?

c - (#ifdef) 与 (#define <boolean>)