2010-12-09 61 views
3

我已經編寫了C++/DLL的C++/CLI包裝器以在C#程序中使用此DLL。AccessViolation,當從C++/CLI調用C++ - DLL

然而,當我調用一個函數,這需要一個char *我得到一個AccessViolation

int Wrapper::Net_methodX(int a, String^ key, long v) 
{ 
    IntPtr ptr = Marshal::StringToHGlobalAnsi(key); 
    pin_ptr<char> cKey = static_cast<char*>(ptr.ToPointer()); 
    int val = methodX(a,cKey, v); // AccessViolation here 

    Marshal::FreeHGlobal(ptr); 
    return val; 
} 

的C++簽名 - 功能

int methodX(int a, char *Key, long v); 

編輯1

只是像以下「別針」也沒有工作:

int Wrapper::Net_methodX(int a, String^ key, long v) 
{ 
    IntPtr ptr = Marshal::StringToHGlobalAnsi(key); 
    char* cKey = static_cast<char*>(ptr.ToPointer()); 
    pin_ptr<char> pinned = cKey; 
    int val = methodX(a,cKey, v); 

    Marshal::FreeHGlobal(ptr); 
    return val; 
} 

EDIT 1 END

EDIT 2

我想也PtrToStringChars以下方式(感謝馬特,也發現了一些文檔here):

int Wrapper::Net_methodX(int a, String^ key, long v) 
{ 
    pin_ptr<const wchar_t> wkey = PtrToStringChars(key); 

    size_t convertedChars = 0; 
    size_t sizeInBytes = ((key->Length + 1) * 2); 
    errno_t err = 0; 
    char * ckey = (char *) malloc(sizeInBytes); 

    err = wcstombs_s(&convertedChars, ckey, sizeInBytes, wkey, sizeInBytes); 

    int val = methodX(A_Symbol_Table,ckey, Value); 

    return val; 
} 

AccessViolation仍然存在,也許這是methodX()(這是第三方DLL)中的錯誤。

EDIT 2 END

我在這裏讀了一些相關的問題,但並沒有找到解決的辦法呢。

任何提示? 謝謝。

回答

0

西蒙, 我嘗試了你的榜樣,我沒有得到一個訪問衝突。這裏是我的代碼:

using namespace System; 
using namespace System::Runtime::InteropServices; 

ref class Wrapper 
{ 
public: 
    static int Net_methodX(int a, String^ key, long v); 
}; 

int methodX(int a, char * pKey, long v) 
{ 
    IntPtr ptr = static_cast<IntPtr>(pKey); 
    String^pString = Marshal::PtrToStringAnsi(ptr); 
    System::Console::WriteLine(pString); 
    return a; 
} 

int Wrapper::Net_methodX(int a, String^ pKey, long v) 
{  
    IntPtr ptr = Marshal::StringToHGlobalAnsi(pKey);  
    pin_ptr<char> cKey = static_cast<char*>(ptr.ToPointer());  
    int val = methodX(a,cKey, v); // AccessViolation here  
    Marshal::FreeHGlobal(ptr);  
    return val; 
} 

void main() 
{ 
    Wrapper wrapper; 
    String^p = gcnew String("Hello"); 
    wrapper.Net_methodX(0, p, 0); 
} 

另外,我有幾點意見:

  1. 這裏閱讀:http://support.microsoft.com/kb/311259
  2. 您使用的是pin_ptr到本機內存。 StringToHGlobalAnsi方法返回本地內存,所以我不認爲在這裏使用pin_ptr是有意義的。如果你正在使用一種方法讓你返回一個指向託管內存的指針(比如PtrToStringChars),那麼pin_ptr會很有意義。除非你修改字符串,否則你可能想要使用PtrToStringChars方法 - 以避免不必要的分配和複製。
  3. 你會發布導致問題的methodX的示例版本嗎?如果我能重現這個問題,我可能會更有幫助。
+0

感謝您在2的澄清。我試圖使用PtrToStringChars(請參閱我的原始發佈中的編輯2),但AccessViolation仍然會發生。不幸的是,methodX()來自第三方DLL,所以沒有源代碼,只有很差的文檔。我只是得到了一個跟蹤,該方法已輸入a,鍵和v的值 – Simon 2010-12-10 08:08:46

+0

爲了消除methodX是問題的可能性,你有沒有嘗試傳入本地分配的char *(實際上,它看起來像你的編輯2試試)?如果你得到一個TRACE的方法已經輸入,那麼我會懷疑methodX是罪魁禍首(或者你正在傳遞它不期望的東西)。 – 2010-12-10 15:04:47

2

我知道這是一個古老的問題,但對於任何偶然發現這個問題尋找答案的人來說,這裏有一些更簡單的解決方案。

  1. 只需使用sprintf來做這樣的轉換:sprintf(cStr, "%s", clrString);。完整的示例請參見my answer to this question
  2. 按照Matt Smith的建議閱讀KB311259。如果您使用的是VS 2008或更高版本,請使用marshal_as<>(KB中的方法#4)。它比該文件中的其他方法簡單得多。