【发布时间】:2016-02-05 18:08:39
【问题描述】:
我是 Interop 的新手,需要从 C# 调用托管 C++ 方法,该方法返回以下 struct 的实例:
typedef struct DataBlock_ {
unsigned char data[10240];
unsigned int numberOfBytes;
unsigned long int startAddr;
} DataBlock;
返回实例的C++方法声明如下:
__declspec(dllexport) DataBlock getDefaultPass( void )
{
DataBlock default_pass = {
{
(char)0xFF,(char)0xFF,(char)0xFF,(char)0xFF,
(char)0xFF,(char)0xFF,(char)0xFF,(char)0xFF,
(char)0xFF,(char)0xFF,(char)0xFF,(char)0xFF,
(char)0xFF,(char)0xFF,(char)0xFF,(char)0xFF,
(char)0xFF,(char)0xFF,(char)0xFF,(char)0xFF,
(char)0xFF,(char)0xFF,(char)0xFF,(char)0xFF,
(char)0xFF,(char)0xFF,(char)0xFF,(char)0xFF,
(char)0xFF,(char)0xFF,(char)0xFF,(char)0xFF
},
32,
0xFFE0
};
return default_pass;
}
我在 C# 中声明了结构和方法如下:
public static partial class My
{
[StructLayout(LayoutKind.Sequential)]
public struct DataBlock
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10240)]
public byte[] data;
//public fixed byte data[10240]; <-- this requires 'unsafe' but still doesn't work
public UInt32 numberOfBytes;
public UInt32 startAddr;
}
[DllImport("my.dll")]
static public extern DataBlock getDefaultPass( );
[DllImport("my.dll")]
static public extern byte sendPassword(DataBlock data);
}
我从 C# 调用方法如下:
var defaultPassword = My.getDefaultPass();
var response = My.sendPassword(defaultPassword);
但是对getDefaultPass() 的调用会抛出
未处理的类型异常 'System.Runtime.InteropServices.MarshalDirectiveException' 发生在 ConsoleApplication1.exe
附加信息:方法的类型签名不是 PInvoke 兼容。
基于this question,我尝试将data的声明更改为public fixed byte data[10240]并将结构标记为unsafe,但随后该方法返回一个实例,其中numberOfBytes和startAddr设置为0,并且随后对sendPassword() 的调用失败(请注意,在this answer 中,随后的调用使用指向结构的指针,而不是实例本身,就像我的情况一样)。那么我应该如何从 C# 调用方法?
该项目面向 .NET 3.5 和 x86。
提前感谢您的帮助。
【问题讨论】:
-
@MatthewWatson 不,该结构实际上是 blittable。虽然返回这样的大型结构很棘手,但 blittability 不是问题。
-
您是否使用 GCC 编译本机代码?如果是这样,它很可能会发出函数以实际采用
ref参数而不是返回结构。真正的签名将类似于static public extern void getDefaultPass(out DataBlock data)。 -
@MatthewWatson 见msdn.microsoft.com/en-us/library/75dwhxf7(v=vs.110).aspx。
byte是 blittable。 blittable 类型的固定大小数组本身是 blittable。因此,byte[](由 OP 定义)是 blittable。 -
@Luaan 我被告知它也是在 Visual Studio 中编译的(我不维护它,也不认为我可以更改它)。这是否有帮助,还是您需要有关构建/链接配置的更多细节?