我在一个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()不会成功运行?
如果你有关于这种现象的任何其他信息,那么请给我你的答案:)。这一切都是我的头脑。欢呼声。
答案 0 :(得分:2)
为什么C()总是返回true?
我发现了一个Microsoft Connect问题,该问题涉及返回bool
,以及它的行为方式。这是问题Native C++ function returning bool always return true in .NET Interop:
你需要用[return: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二进制文件。在这种情况下,将抛出异常;如果您没有发现异常,您的申请将被终止。