我在C#中使用PInvoke来调用C ++ DLL中的函数。返回的对象包含bool,但该值永远不正确。我已经阅读了几篇关于C ++ bool是1字节的文章,而在C#中bool是4字节。我还看到了当函数返回bool时如何克服这个问题的例子,但我的函数是返回一个包含bool的对象。我没有找到任何展示如何处理这种情况的文章。
例如,我有两个结构。一个用于输入非托管DLL的函数,另一个用于定义输出:
public struct MyInput
{
public int id;
public string ModelNumber;
}
public struct MyOutput
{
public int SomeValue;
public double AnotherValue;
public bool IsValid;
}
[DllImport("MyUnmanaged.dll", EntryPoint = "?Unit@@YA?AUMyOutput@@UMyInput@@@Z")]
public static extern MyOutput Unit(ref MyInput UnitInput);
MyOutput无法按上述定义工作,因为签名无效。所以我把IsValid改为:
public int IsValid;
这会处理无效的签名错误,但是IsValid的值不像我期望的那样是0或1。相反,它是-858993664。我也尝试过更改为byte,但返回的值始终为0.
我不明白如何编组MyOutput结构中的bool或如何定义它以便我得到一个有效的bool - 1或0。
是的,我没有对非托管DLL的任何控制......有人可以让我知道如何在MyOutput结构中定义bool吗?
修改
我给出的是非DLL的DLL的.DLL和.h。在.h中,所讨论的bool定义为:
bool IsValid;
答案 0 :(得分:2)
-858993664 == 0xcccccc00。当然,当您不使用byte
或在成员上应用[MarshalAs(UnmanagedType.U1)]
属性时,这是您期望获得的价值。显然,您正在使用该DLL的调试版本,它将内存初始化为0xcccccccc。
所以你真的获得了IsValid的false
值。当然没有合理的猜测你可以到这里为什么本机代码不满意。您需要与C程序员交谈以了解有关它的更多信息。在部署程序时,您还需要他的帮助,您无法发送该DLL的调试版本。
答案 1 :(得分:1)
根据此online demangler,您的非托管函数具有以下签名:
struct MyOutput __cdecl Unit(struct MyInput)
所以你的C#声明应该是:
[DllImport("MyUnmanaged.dll", EntryPoint = "?Unit@@YA?AUMyOutput@@UMyInput@@@Z",
CallingConvention = CallingConvention.Cdecl)]
public static extern MyOutput Unit(MyInput UnitInput);
换句话说,您使用了错误的调用约定,并将参数传递给ref
而不是值。
您还发现无法编组返回值结构类型,因为它包含bool
字段。您需要将其更改为byte
或int
,具体取决于非托管结构声明的内容。看起来,根据您的编辑,头文件将其声明为bool
,这是单字节类型,因此您应该使用byte
。