Zé *_*los 7 c# pinvoke marshalling
我有一个非托管的DLL导出以下函数:
SomeData* test();
Run Code Online (Sandbox Code Playgroud)
我们假设SomeData为:
typedef struct _Data Data;
struct _Data{
int a;
int b;
}
Run Code Online (Sandbox Code Playgroud)
现在我想用C#代码调用这个函数.我开始定义像这样自定义编组所需的C#Struture:
[StructLayout(LayoutKind.Sequential)]
public class SomeData
{
public Int32 a;
public Int32 b;
}
Run Code Online (Sandbox Code Playgroud)
现在,我宣布托管函数:
[DllImport("DynamicLibrary.dll", CharSet=CharSet.Auto)]
[return: MarshalAs(UnmanagedType.LPStruct)]
public static extern SomeData test();
Run Code Online (Sandbox Code Playgroud)
在主要功能我有:
IntPtr ptr = test();
Run Code Online (Sandbox Code Playgroud)
这样做,我得到MarchalDirectiveException:"无法编组'返回值':无效的托管/非托管类型组合(Int/UInt必须与SysInt或SysUInt配对)."
我没有为C#中的SomeData分配内存,因为我希望这个内存在C函数中分配,我将使用Marshal.Copy将它传递给托管内存.
有任何想法吗?谢谢
------------------------ JaredPar ANSWER之后的编辑--------------------
事实上,我在将代码复制到我的问题时犯了一个错误.我使用的真正托管签名是:
[DllImport("DynamicLibrary.dll",CharSet = CharSet.Auto)]
[返回:MarshalAs(UnmanagedType.LPStruct)]
public static extern IntPtr test();
JaredPar的答案仍然相关.为了获得正确的行为,我有两个选择:
1)使用'public static extern IntPtr test();' (没有MarshalAs属性)签名然后像JaredPar建议的那样访问返回的指针.
2)使用'public static extern SomeData test();' (使用MarshalAs属性)然后只需使用SomeData sd = test();
Jar*_*Par 10
声明托管函数时,需要将指针类型与参考值或IntPtr值匹配.在这种情况下,LPStruct修饰符将无济于事.最简单的解决方案是将test的返回值转换为IntPtr而不是SomeData因为本机方法返回指针值.然后,您可以编写以下包装器
[DllImport("DynamicLibrary.dll", CharSet=CharSet.Auto)]
public static extern IntPtr test();
public static SomeData testWrapper() {
var ptr = test();
try {
return (SomeData)Marshal.PtrToStructure(ptr, typeof(SomeData));
} finally {
// Free the pointer here if it's allocated memory
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11473 次 |
| 最近记录: |