2014-01-15 182 views
-2

我有這個C函數內部的一個dll,我從VB.Net調用。爲什麼布爾函數返回false返回true

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()不能成功運行?

如果您有關於這種現象的任何其他信息,請給我您的答案:)。這是我的頭頂。乾杯。

+6

我不知道你在問什麼。請重新說明你的問題。爲了澄清,您_are_檢查函數的返回值..因爲該語句是一個條件語句,放置在那裏的值是該函數的布爾返回值。 –

+0

您聲明「我們實際返回的是C()的值,我們正在檢查C()是否成功運行。」西蒙說,那不是真的。混淆可能來自許多平臺上的通用慣例,以返回值,如果函數調用完成本應該執行的操作,則返回值爲true;如果函數調用失敗,則返回值爲false的值。值仍然在返回,這只是值遵循一個有用的約定。 –

+0

如果函數*不能*「成功運行」,那麼當程序捕獲異常或崩潰時,您會知道它。 – paddy

回答

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字節的布爾值...所以任何高位24位的垃圾將被編組解釋爲'true'層。

因此,換句話說,在VB Boolean類型不正確地得到映射到贏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二進制文件,在這種情況下,將拋出異常;如果您沒有發現異常,您的應用程序將被終止。

+0

優秀的答案,值得更多的將問題變成一個優秀的問題。 –

相關問題