非托管到托管返回对象,包含BOOL

本文关键字:包含 BOOL 返回 对象 | 更新日期: 2023-09-27 18:15:10

我在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。我也试过改成字节,但是返回值总是0。

我不明白如何封送MyOutput结构体内部的bool值,或者如何定义它,以便我得到一个有效的bool值- 1或0。

Btw,我没有任何非托管DLL的控制…

有人可以为我提供一个如何定义MyOutput结构内部的bool的想法吗?

编辑

我得到的只是。DLL和。h表示非托管DLL。在.h中,所讨论的bool定义为:

bool IsValid;

非托管到托管返回对象,包含BOOL

-858993664 == 0xcccccc00。当然,当您不使用byte或在成员上应用[MarshalAs(UnmanagedType.U1)]属性时,这是您期望得到的那种值。显然,您正在使用该DLL的调试版本,它将内存初始化为0xcccccccc。

所以你是真的得到一个false值为IsValid。当然,这里没有合理的猜测可以解释为什么本机代码不满意。你需要和C程序员谈谈,了解更多。当需要部署程序时,您还需要他的帮助,因为您无法发布该DLL的调试版本。

根据这个在线需求器,您的非托管函数有这样的签名:

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