为什么返回false的Boolean Function返回true

时间:2014-01-15 01:04:08

标签: c vb.net

我在一个dll中有这个C函数,我从VB.Net调用。

C代码:

extern "C" {
    __declspec(dllexport) bool __stdcall C(bool ret);
}

extern bool __stdcall C(bool ret){
    return ret;
}

以下是调用上述内容的VB.Net代码:

Imports System.Runtime.InteropServices

Module Module1

    <DllImport("foo.dll", CallingConvention:=CallingConvention.StdCall)> _
    Private Function C(ByVal param As Boolean) As Boolean
    End Function

    Sub Main()
        System.Console.WriteLine("C(False): {0}", C(False))
        System.Console.WriteLine("C(True): {0}", C(True))
    End Sub

End Module

当我运行上面的代码时,我得到:

C(False): True
C(True): True

看来我们实际上并没有从C()返回值,而是返回C()成功运行的事实。

为什么C()始终返回true? 什么时候C()不会成功运行?

如果你有关于这种现象的任何其他信息,那么请给我你的答案:)。这一切都是我的头脑。欢呼声。

1 个答案:

答案 0 :(得分:2)

  

为什么C()总是返回true?

我发现了一个Microsoft Connect问题,该问题涉及返回bool,以及它的行为方式。这是问题Native C++ function returning bool always return true in .NET Interop

  

你需要用[re​​turn:MarshalAs(UnmanagedType.I1)]装饰P / Invoke声明。   Bool编组到Win32 BOOL - 这是一个4字节的值....你的函数返回一个1字节的bool ...所以高位24位的任何垃圾......将由编组层解释为'true'

换句话说,VB Boolean类型被错误地映射到Win 32 BOOL(4个字节),这与C布尔值(1个字节)不同。

要解决此问题,您可以执行以下两项操作中的一个

选项1 - 更改VB P / Invoke签名

您可以告诉编组代码映射到一个字节bool

VB P / Invoke签名中的这一行:

Private Function C(ByVal param As Boolean) As Boolean

应更改为:

Private Function C(<MarshalAs(UnmanagedType.I1)> ByVal param As Boolean) As _
<MarshalAs(UnmanagedType.I1)> Boolean

选项2 - 更改C功能签名

您可以将C单字节bool类型更改为Win 32四字节BOOL,如下所示:

extern "C" {
    __declspec(dllexport) BOOL __stdcall C(BOOL ret);
}

extern BOOL __stdcall C(BOOL ret){
    return ret;
}

<强>结果

如果我使用上述任何一项更改运行程序,则输出为:

C(False): False
C(True): True

现在,返回值反映了参数值。


  

何时C()无法成功运行?

您编写的代码通常会成功运行。我能想到它失败的唯一情况是 VB.Net代码找不到C二进制文件。在这种情况下,将抛出异常;如果您没有发现异常,您的申请将被终止。