Маршал StringBuilder для char * в C ++ / CLI (для IN / OUT) - PullRequest
1 голос
/ 26 июля 2011

Я загружаю 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 * и обратно, чтобы сохранить ответ нативной функции?

Ответы [ 2 ]

1 голос
/ 26 июля 2011

Я вижу две проблемы: во-первых, вы сопоставляете объект 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;
}
0 голосов
/ 20 декабря 2016

Вы можете напрямую передавать строки 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.очень удобный инструмент для сопряженияУдачи.(Я использовал эти тонны фрагментов.)

...