我不得不把带有字符串数据的结构从C#代码传递到C++ dll。
c++代码
typedef struct
{
LPCSTR lpLibFileName;
LPCSTR lpProcName;
LPVOID pPointer1;
LPVOID pPointer2;
} ENTITY, *PENTITY, *LPENTITY;
extern "C" __declspec(dllexport) int Test(LPENTITY entryList, int size);
int Test(LPENTITY entryList, int size)
{
for (int i = 0; i < size; i++)
{
ENTITY e = entryList[i];
// the char* value doesn't get passed correctly.
cout << e.lpLibFileName << e.lpProcName << endl;
}
return 0;
}c#代码
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
private class Entity
{
public string lpLibFileName;
public string lpProcName;
public IntPtr pPointer1;
public IntPtr pPointer2;
}
[DllImport("cpp.dll")]
private static extern int Test(
[In, Out, MarshalAs(UnmanagedType.LPArray)]Entity[] entities,
int size);
static void Main(string[] args)
{
var entries = new[]
{
new Entity
{
lpLibFileName = "comdlg32",
lpProcName = "PrintDlgExW",
pPointer1 = Marshal.GetFunctionPointerForDelegate(new PrintDlgEx(PrintDlgExCallback)),
pPointer2 = IntPtr.Zero,
},
new Entity
{
lpLibFileName = "shell32",
lpProcName = "ShellAboutW",
pPointer1 = Marshal.GetFunctionPointerForDelegate(new ShellAbout(ShellAboutCallback)),
pPointer2 = IntPtr.Zero,
},
};
var ret = Test(entries, entries.Length);
}PINVOKE已触发,但无法正确传递lpLibFileName和lpProcName等char*数据。我错过了什么吗?如何纠正它?
谢谢。
发布于 2013-06-30 01:43:22
您的代码将C#类映射到本机结构。因为C#类是引用类型,所以它将被编组为引用。因此,您的代码传递了一个引用数组,该数组被编组为本机端的指针数组。
但是本机代码需要一个指向值类型结构数组的指针。因此,最简单的解决方案是将Entity的声明更改为struct而不是class。
我能看到的其他问题:
cdecl调用约定。您需要更改C#代码以匹配.Out修饰数组参数。不能将对string字段的修改封送回托管代码。GetFunctionPointerForDelegate的委托保持活动状态,以阻止收集委托。发布于 2013-06-29 22:01:27
当传递像自定义结构数组这样的参数时,在定义自己的数据结构时使用'struct‘而不是'class’。在我把它改回struct之后,一切都运行得很好。
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
private struct Entity
{
public string lpLibFileName;
public string lpProcName;
public IntPtr pPointer1;
public IntPtr pPointer2;
}https://stackoverflow.com/questions/17380270
复制相似问题