在c++ /CLI中将StringBuilder封送为char*(用于输入/输出)

本文关键字:用于 输出 char 输入 CLI c++ 中将 StringBuilder | 更新日期: 2023-09-27 18:03:25

我正在加载一个c++/CLI包装dll到我的c#软件中,需要一些char*参数用于底层的本地c++ dll!

我发现我需要传递一个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
}

如何使用StringBuilder并将其封送为char*并返回以保存本机函数的答案?

在c++ /CLI中将StringBuilder封送为char*(用于输入/输出)

我看到的问题有两个:第一,您正在将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,                 // 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;
}

您可以在以下工具的帮助下直接传入c#字符串:(简单!)

您需要利用一些互操作能力,将字符串复制到非托管堆内存中,并返回给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层的头文件中。非常方便的接口工具。祝你好运。