我正在尝试从某些 C# 调用 Win32 DLL。DLL函数声明如下:
extern "C" __declspec(dllexport) UINT foo(TCHAR** list[], int& listSize, TCHAR* error);
在 C# 中,我像这样声明外部函数:
[DllImport("foo.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
static extern uint foo(StringBuilder[] list, ref int listSize, StringBuilder error);
我的问题与list参数有关,它是 StringBuilder 类的数组。
我调用 DLL 函数的一些测试代码如下:(注意:我意识到缺少边界检查等。在这个阶段,我只是想让事情正常工作)。
// allocate a buffer for a possible error message being returned
StringBuilder error = new StringBuilder(1000);
// allocate buffers for the list of strings returned
StringBuilder[] list = new StringBuilder[10];
for (int i = 0; i < 10; i++)
{
list[i] = new StringBuilder(1000);
}
int listSize = list.Length;
uint result = foo(list, ref listSize, error);
将 StringBuilder 作为错误参数的缓冲区传递,可以正常工作。我可以在 DLL 中设置它的内容,如下所示:
_tcscpy(error, _T("Something went wrong");
当 C# 对foo的调用返回时,字符串错误变量具有我们在 DLL 中设置的文本。
但是,我无法弄清楚如何编组StringBuilder[] 列表参数。
在 C++ 中,我可以设置列表数组的内容:
_tcscpy((*list)[0], _T("First item"));
// and so on...
而且,即使没有由于任何可能的编组问题而发生崩溃,当对foo()的调用返回时,C# 中的列表也不包含我们在 C++ 中设置的任何字符串。
我猜问题出在DllImport以及我如何声明list参数应该被编组。
顺便说一句,示例 DLL 有一个匹配函数,然后调用该函数以释放上面显示的示例foo返回的“TCHAR** 列表” 。