未托管到包含BOOL的托管返回​​对象

时间:2014-07-27 14:15:41

标签: c# c++ pinvoke

我在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;

2 个答案:

答案 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字段。您需要将其更改为byteint,具体取决于非托管结构声明的内容。看起来,根据您的编辑,头文件将其声明为bool,这是单字节类型,因此您应该使用byte