2010-06-15 48 views
3

我是一個C++ dll文件,一個lib文件和一個頭文件。我需要從我的C#應用​​程序中調用它們。C#調用C++ DLL獲取EntryPointNotFoundException

頭文件是這樣的:

class Clog ; 

class EXPORT_MACRO NB_DPSM 
{ 
private: 
    string sFileNameToAnalyze ; 

    Clog *pLog ; 

    void write2log(string text) ; 

public: 
    NB_DPSM(void); 
    ~NB_DPSM(void); 

    void setFileNameToAnalyze(string FileNameToAnalyze) ;  
    int WriteGenbenchData(string& message) ; 
}; 

在我的C#代碼,我有那些代碼:

internal ReturnStatus correctDataDLL(string rawDataFileName) 
     { 
      if (rawDataFileName == null || rawDataFileName.Length <= 0) 
      { 
       return ReturnStatus.Return_CannotFindFile; 
      } 
      else 
      { 
       setFileNameToAnalyze(rawDataFileName);       
      } 

      string msg = ""; 
      int returnVal = WriteGenbenchData(ref msg); 


      return ReturnStatus.Return_Success; 
     } 

[DllImport("..\\..\\thirdParty\\cogs\\NB_DPSM.dll")] 
public static extern void setFileNameToAnalyze(string fileName); 


[DllImport("..\\..\\thirdParty\\cogs\\NB_DPSM.dll")] 
public static extern int WriteGenbenchData(ref string message); 

我在setFileNameToAnalyze(rawDataFileName);說法得到了EntryPointNotFoundException

幾個問題:

  1. ,我需要的是lib文件添加到我的C#項目的地方?怎麼樣?

  2. 我需要將頭文件添加到我的C#項目嗎?怎麼樣? (目前沒有編譯錯誤)

  3. 我想刪除那些"..\\..\\thirdParty\\cogs\\"硬編碼路徑。如何做到這一點?

  4. 如何搭乘那個EntryPointNotFoundException

感謝,

回答

2

您不需要在C#項目中包含頭文件或lib文件。無論如何,這些文件對你無用。

您得到EntryPointNotFound異常的原因是您爲這些入口點提供了不正確的名稱。編譯C++項目時,編譯器會通過添加有關參數和返回類型的附加信息來改變名稱。 (您可以使用dumpbin.exe實用工具查看這些入口點。)

然而,真正的問題是您的DLL顯然包含一個C++類。 「setFileNameToAnalyze」和「WriteGenbenchData」是該類的實例方法,而不是靜態函數。如果不先創建NB_DPSM類的實例,則無法調用它們。

只用P/Invoke就可以做到這一點,但在這一點上我認爲它可能比它的價值更麻煩。您應該創建一個託管C++類庫來包裝舊的DLL。

至於你的問題的第(3)部分,只需刪除路徑並確保NB_DPSM.dll與輸出文件的結果位於同一個bin目錄中。

2

地方的任何類以外的功能(如全局函數),並在extern "C" { ... }塊。

你不需要C#中的頭文件。 (這就是[DllImport]所做的)

+0

爲什麼需要「extern」C「{}」塊? – 5YrsLaterDBA 2010-06-17 19:56:45

+3

@ 5YrsLaterDBA:防止[name mangling](http://en.wikipedia.org/wiki/Name_mangling#Name_mangling_in_C.2B.2B)。 – SLaks 2010-06-17 20:23:30

2

能試着讓自己的非託管C++ DLL作爲墊片,使用所提供的DLL 有1種方法

extern "C" int GenBenchData(const string &filename, string & message){ 
    NB_DPSM builder; 
    builder.setFileNameToAnalyze(filename); 
    return builder.WriteGenbenchData(message); 
} 

在C#中聲明與

[DllImport("shim.dll", CharSet = CharSet.Auto)] 
static extern int GenBenchData([MarshalAs(UnmanagedType.LPStr)]string filename, StringBuilder message); 
1

而且提防calling convention的。如果您的DLL真的是C++,請使用工具將導出的名稱可視化(如鏈接的文章中提到的depend.exe)。每個C++編譯器都有其自己的裝飾方案,使其適應起來有點繁瑣。或者,您可以使用包裝器管理的C++程序集,鏈接到C++ DLL。如果它只是一個C接口,請注意調用約定和字體大小(常見的陷阱:在C/C++中,C#中的64位是32位)