2009-02-21 40 views
7

我已經構建了一個C++ dll,我想從C#代碼調用。我可以調用一個函數,但是當C#代碼嘗試加載dll時,另一個會引發異常。從C++ dll導出函數到C#P/Invoke

頭看起來像這樣:(?這是什麼富= foo的名稱字段的意思)

extern "C" __declspec(dllexport) BOOL Install(); 
extern "C" __declspec(dllexport) BOOL PPPConnect(); 

這將產生與略顯混亂出口表中的DLL:

File Type: DLL 

Section contains the following exports for PPPManager.dll 

00000000 characteristics 
499F44F0 time date stamp Fri Feb 20 16:04:00 2009 
    0.00 version 
     1 ordinal base 
     2 number of functions 
     2 number of names 

ordinal hint RVA  name 

     1 0 000078E4 Install = Install 
     2 1 000079DC PPPConnect = PPPConnect 

我的P /調用聲明如下所示:

[DllImport("PPPManager.dll")] 
private static extern bool Install(); 

[DllImport("PPPManager.dll")] 
private static extern bool PPPConnect(); 

對安裝的調用沒有任何異常返回,但當我調用PPPConnec t,我得到一個MissingMethodException - 「在PInvoke DLL'PPPManager.dll'中無法找到入口點'PPPConnect'」。

我試着從安裝函數聲明中刪除extern和declspec指令,以便PPPConnect是唯一導出的函數,並且這仍然不會讓我調用PPPConnect。

我也試着按順序做DllImport;這給出了與名稱調用相同的結果 - 安裝返回,但PPPConnect拋出異常「無法找到入口點'#2'...」。

互操作的日誌給:

[pinvokeimpl][preservesig] 
bool invivodata.Common.System.IPAQUtils::Install(); 
BOOLEAN (I1_WINBOOL_VAL) Install(); 

JIT ERROR FOR PINVOKE METHOD (Managed -> Native): 
[pinvokeimpl][preservesig] 
bool invivodata.Common.System.IPAQUtils::PPPConnect(); 
BOOLEAN (I1_WINBOOL_VAL) PPPConnect(); 

這是好我的專業領域之外,因此任何建議或想法將受到歡迎。

感謝, 保羅

編輯: 事實證明,這個代碼工作;問題是最新的dll沒有傳播到設備。 D'哦!

+0

我從來沒有聽說過這種互操作的日誌 - 如何使一個/查看? – Charlie 2009-02-21 02:04:23

+0

http://blogs.msdn.com/netcfteam/archive/2005/07/24/442609.aspx 我剛開始使用它來嘗試和調試這個問題,但它似乎爲我節省了很多實時調試MissingMethodExceptions。 – Symmetric 2009-02-24 00:31:25

回答

8

您是否在您的dll項目中使用.def文件來導出這些功能?如果是這樣,請將其刪除並重試。這只是一個猜測,因爲它看起來像你做出extern「C」declspec(dllexports)時的輸出結果。

我使用

extern "C" __declspec(dllexport) BOOL Install(); 
extern "C" __declspec(dllexport) BOOL PPPConnect(); 

使用您PInvoke的聲明一個簡單的C#應用​​程序一個簡單的C++ DLL並嘗試了這一點,它工作得很好。

當我做了DUMPBIN /上我看到了DLL導出:

文件的轉儲PPPManager.dll

文件類型:DLL

段包含PPPManager.dll

以下出口
00000000 characteristics 
499F6C2D time date stamp Fri Feb 20 20:51:25 2009 
    0.00 version 
     1 ordinal base 
     2 number of functions 
     2 number of names 

ordinal hint RVA  name 

     1 0 000110CD Install = @ILT+200(_Install) 
     2 1 00011069 PPPConnect = @ILT+100(_PPPConnect) 

請注意,導出的名稱在我的情況下是不同的。

0

偉大的信息,但正如你所說,一切都是爲了這裏。嘗試安裝適用於Windows的調試工具並運行:

kd -z \path\to\PPPManager.dll -y \path\to\PPPManager.pdb -c "x pppmodule!*" 

可以更好地轉儲符號表;這是一個瞎炮爲好,但你也可以嘗試:

extern "C" 
{ 
    __declspec(dllexport) BOOL Install(); 
    __declspec(dllexport) BOOL PPPConnect(); 
}; 

的情況下,__declspec正在做一些奇怪的。

1

這可能像PPPConnect那樣簡單,可能會被操作系統誤解。嘗試執行InstallPPPConnect作爲無操作(只需讓他們返回TRUE而不做其他任何操作),然後查看錯誤是否仍然存在。如果是這樣,請嘗試交換它們導出的順序(仍然是no-ops),並查看問題是否與排序(不太可能)或其他問題相關聯。

您也可以使用圖形工具depends來確認DLL的導出表的樣子,但我懷疑問題是來自這些宿舍。

+0

這些是隔離真實問題的好主意。您也可以嘗試添加第三個函數並查看該函數的情況。 – Charlie 2009-02-21 02:03:17

1

根據您的描述安裝和PPPConnect只有名稱不同。我想你只需使用舊的.dll版本與你的C#應用​​程序。一個沒有定義PPPConnect的人。

聲明看起來是正確的(據我可以判斷沒有來源)。

0

使用依賴學步車,打開你的DLL來驗證什麼方法都可以