开发者

Marshal StringBuilder to char* in C++/CLI (for IN/OUT)

I'm loading a C++/CLI wrapping dll into my C# software and need some char* parameters for the underlying native C++ dll!

I found out that I need passing a StringBuilder for save the answer without getting some Access violations?!

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

}

How it is possible to use the StringBuilder and marshal it to char* and back to save the answer of native function?


The problems I see are two: first, that you are mapping a UNICODE object to an MBCS or ASCII object, and second that StringBuilder does not pin automatically either. I would recommend you do this:

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,                 // ch@rs with accents
        strVal,                            // UNICODE string
        wchLen,                            // Number of UNICODE ch@rs
        pchVal,                            // ASCII string
        pchLen,                            // Max number of ASCII ch@rs
        0,                                 // No default ch@rs
        0                                  // No default flag
    );
    pchVal[nclen] = '\0';

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

    // Cleanup
    delete[] pchVal;
}


You can directly pass in c# strings with help from the following tools: (EASY!)

You need to take advantage of some interop abiliteis to copy the strings into unmanaged heap memory and back for c++ native to use. These two helpers should do the trick when used in your c++/cli layer. Pass the string in as std::string& to the native c++ layer. When native c++ is done copy back to managed memory.

//////////////////////////////////////////////////
// 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
}

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

Throw the above code in a header file in your c++/cli layer. very handy interfacing tools. Good luck. (I've used these snippets tons.)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜