簡體   English   中英

從C#調用C ++ dll時的C#和C ++,運行時錯誤

[英]C# & C++, runtime error when call C++ dll from C#

我為C#編寫了一個C ++包裝器DLL來調用。 DLL已經過測試,並且在我的C ++測試程序中運行良好。

現在與C#集成,我得到了運行時錯誤並崩潰了。 無法使用調試器查看更多詳細信息。

C ++方面只有一個方法:

#ifdef DLLWRAPPERWIN32_EXPORTS
#define DLLWRAPPERWIN32_API __declspec(dllexport)
#else
#define DLLWRAPPERWIN32_API __declspec(dllimport)
#endif

#include "NB_DPSM.h"

extern "C" {
 DLLWRAPPERWIN32_API int WriteGenbenchDataWrapper(string fileNameToAnalyze, 
  string parameterFileName,  
  string baseNameToSaveData,
  string logFileName,
  string& message) ;
}

在C#方面,有一個定義,

[DllImport("..\\..\\thirdParty\\cogs\\DLLWrapperWin32.dll")]
public static extern int WriteGenbenchDataWrapper(string fileNameToAnalyze, 
              string parameterFileName,  
              string baseNameToSaveData,
              string logFileName, 
              ref string message);

並致電:

 string msg = "";
    int returnVal = WriteGenbenchDataWrapper(rawDataFileName, 
                   parameterFileName, outputBaseName, logFileName, ref msg);

我想函數的最后一個參數肯定有問題。 string& C ++中的ref string應該是C#中的ref string嗎?

EDIT:

我們真的需要extern "C"嗎?

EDIT 2:

在我從dll中刪除extern "C后,我得到了EntryPointNotFoundException。當我使用DLL Export Viewer查看dll時,我發現函數名稱為”int __cdecl WriteGenbenchDataWrapper(class std :: ...“我需要嗎?包括“__cdecl”?

有一堆用PInvoke編組的規則。 manchaned和unmanaged之間的Marsheling參考

首先關注C#方面。 如果您事先知道消息的合理大小,則可以使用StringBuilder類型並定義該大小,例如。

[DllImport("DLLWrapperWin32.dll")]
public static extern int WriteGenbenchDataWrapper(string fileNameToAnalyze, 
                                                    string parameterFileName,   
                                                    string baseNameToSaveData,
                                                    string logFileName, 
                                                    StringBuilder message
                                                    int messageLength );

來自姓名消息(和其他帖子)的印象表示您不知道前面的大小,並且您不會將部分消息傳遞給該功能,所以也許

[DllImport("DLLWrapperWin32.dll")]
public static extern int WriteGenbenchDataWrapper(in string fileNameToAnalyze, 
                                                    in string parameterFileName,   
                                                    in string baseNameToSaveData,
                                                    in string logFileName, 
                                                    out string message );

現在在C / C ++方面 - 匹配第二個定義

extern "C" // if this is a C++ file to turn off name mangling for this function only
int WriteGenbenchDataWrapper( char * fileNameToAnalyze, 
                              char * parameterFileName,   
                              char * baseNameToSaveData,
                              char * logFileName, 
                              char ** message ) {
  string internalMessage;
  SomeFunc( internalMessage ); // these functions won't have extern "C" applied
  * message = (char *)::CoTaskMemAlloc(internalMessage.length()+1); 
  strcpy(* message, internalMessage.c_str());
}

考慮unicode / ansi字符串也很重要,請參考[MarshalAsAttribute(UnmanagedType.LPWSTR)]

對於發布模式,您需要刪除開發路徑設置“.. \\ .. \\ thirdParty \\ cogs”

在您的C ++代碼中:

我總是需要外部的“C”。 如果不這樣做,C ++會破壞函數名稱(需要修改以支持函數重載)。 外部“C”告訴它不要這樣做。

我還將函數聲明為__stdcall。 我相信你可以告訴C#使用哪種類型的調用約定,但我認為__stdcall是默認值。

至於傳遞一個字符串對象,我不確定,我堅持只使用原語進行參數傳遞,所以我會使用const char *並在我的C ++代碼中進行相應的調整。

另外,我盡量避免通過引用傳遞。 相反,如果我需要返回幾個值,我將設置一系列getter來處理這個(const char *作為IntPtr返回)。

在您的C#代碼中:

我使用String作為const char *,int作為int,依此類推。 我相信微軟有一個圖表可以告訴你什么應該分為什么。

處理返回的字符串時,需要將其轉換為ANSI。 這可以通過調用Marshal.PtrToStringAnsi()來完成。

例如:

在我的C ++代碼中:

extern "C" __declspec(dllexport) const char* __stdcall GetCompany(const char *In) {
  return MyGetCompany(In); // Calls the real implementation
}

在我的C#代碼中:

[DllImport("TheDLL.dll", EntryPoint = "GetCompany")]
private static extern IntPtr privGetCompany(String In);

// Call this one, not the one above:
public String GetProvince(String In)
{
  return Marshal.PtrToStringAnsi(privGetCompany(In));
}

最后要注意的是,如果您在64位計算機上運行,​​“任何CPU”配置將生成64位C#可執行文件,這將需要64位DLL。 如果您只有32位DLL,則需要添加配置(x86)。

您收到的錯誤消息表明您的C#程序可能正確地找到了DLL和函數,因此名稱修改可能不是問題。 這聽起來像調用約定問題或參數傳遞的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM