2011-07-26 144 views
1

我正在加載一個C++/CLI包裝dll到我的C#軟件中,並且需要一些char *參數用於底層的本地C++ dll!Marshal StringBuilder to char * in C++/CLI(for IN/OUT)

我發現我需要傳遞一個StringBuilder來保存答案而沒有得到一些訪問衝突?

C#

StringBuilder sB = new StringBuilder(); 
WrapperClass wC = new WrapperClass(); 
wC.Function(sB); 

C++/CLI

void WrapperClass::Function(StringBuilder ^sB) 
{ 
    nativeObject->Function(charString); // need the marshaled sB 
} 

C++

void NativeObject::Function(char *charString) 
{ 

    // do something and save answer to charString 

} 

它如何能夠使用第e StringBuilder並將其編組爲char *並返回以保存本機函數的答案?

+1

請編輯您的問題,以便清楚要問什麼。 –

+0

什麼不清楚? – leon22

+0

這不是一個問題,它是一個狀態。在句子結尾處打一個問號並不構成問題。 –

回答

1

我看到的問題有兩個:首先,您將UNICODE對象映射到MBCS或ASCII對象,其次是StringBuilder不會自動引腳。我建議你這樣做:

void WrapperClass::Function(StringBuilder^ sB) 
{ 
    // Pin a copy of the string 
    String^ strVal = sB->ToString(); 
    pin_ptr<const wchar_t> psVal = PtrToStringChars(strVal); 

    // Translate the UNICODE string to MBCS 
    int wchLen = wcslen(psVal); 
    int pchLen = wchLen * 2 + 1; 
    char* pchVal = new char[pchLen]; 
    int nclen = WideCharToMultiByte(
     CP_ACP,       // Source codepage (default) 
     WC_COMPOSITECHECK,     // [email protected] with accents 
     strVal,       // UNICODE string 
     wchLen,       // Number of UNICODE [email protected] 
     pchVal,       // ASCII string 
     pchLen,       // Max number of ASCII [email protected] 
     0,         // No default [email protected] 
     0         // No default flag 
    ); 
    pchVal[nclen] = '\0'; 

    // Pass the MBCS string to MBCS function 
    nativeObject->Function(pchVal); // need the marshaled sB 

    // Cleanup 
    delete[] pchVal; 
} 
+0

謝謝!我會嘗試! – leon22

0

您可以在C#中的字符串與幫助下,直接通過從以下工具:(!EASY)

你需要採取一些互操作的優勢abiliteis複製字符串轉換爲非託管堆內存,並返回原生C++使用。這兩個助手應該在你的C++/cli層中使用。將字符串作爲std :: string &傳遞給本機C++層。當原生C++完成時,將其複製回託管內存。

////////////////////////////////////////////////// 
// Marshalling Strings Functions 

inline 
String^ToManagedString(const char * pString) { 

    return Marshal::PtrToStringAnsi(IntPtr((char *)pString)); // Marshal pString into Managed Memory. return as a C# string reference (^). 

} 

inline 
const std::string ToStdString(String^strString) { 
    IntPtr ptrString = IntPtr::Zero; 
    std::string strStdString; 
    try { 
     ptrString = Marshal::StringToHGlobalAnsi(strString);  // Marshal a C# String reference into unmanaged HEAP memory space. 
     strStdString = (char *)ptrString.ToPointer();   // Convert C# IntPtr to char* implicitly, call assignment operator of std::string to copy. 
    } 
    finally { 
     if (ptrString != IntPtr::Zero) { 
      Marshal::FreeHGlobal(ptrString); 
     } 
    } 
    return strStdString;           // return std::string copied out of interop unmanaged heap space 
} 

////////////////////////////////////////////////////// 

將上面的代碼放在C++/cli圖層的頭文件中。非常方便的接口工具。祝你好運。 (我已經使用了這些片段噸。)