【问题标题】:Marshal StringBuilder to char* in C++/CLI (for IN/OUT)在 C++/CLI 中将 StringBuilder 编组为 char*(用于 IN/OUT)
【发布时间】:2011-07-26 11:39:29
【问题描述】:

我正在将一个 C++/CLI 包装 dll 加载到我的 C# 软件中,并且需要一些用于底层原生 C++ dll 的 char* 参数!

我发现我需要传递一个 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* 并返回以保存本机函数的答案?

【问题讨论】:

  • 请编辑您的问题,以便清楚询问的内容。
  • 这不是一个问题,这是一个statemnet。在句尾打一个问号并不代表它是一个问题。
  • 好的!问题在于代码!我现在添加了更多信息!
  • 这对我来说没有意义。为什么要使用 StringBuilder 映射到本机 char[]?您应该使用 char[] 并确保它以 null 结尾。
  • 看这里:books.google.at/…(char* IN 和 OUT 的默认映射是 StringBuilder)

标签: c# c++-cli char marshalling stringbuilder


【解决方案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,                 // 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;
}

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-20
      • 1970-01-01
      • 1970-01-01
      • 2016-04-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多