Передайте строку C# C++ и передайте результат C++ (строка, char*.. безотносительно) к C#

Я попробовал разные вещи, но я рассердился с Interop.

(здесь последовательность слов не отнесена в тип variabile, но "набор символа"): у Меня есть неуправляемая функция C++, определенная в dll, к которому я пытаюсь получить доступ от C#, эта функция имеет строковый параметр и строковое возвращаемое значение как это:

string myFunction(string inputString)
{
}

Какова должна быть строка в стороне C++? и C# один? и каким параметрам нужен DllImport для этого?

13
задан Smjert 1 February 2010 в 18:58
поделиться

4 ответа

Я нашел, что лучше всего работать, так это быть более откровенным о том, что здесь происходит. Наличие строки в качестве возвращаемого типа, вероятно, не рекомендуется в данной ситуации.

Распространенным подходом является передача на стороне С++ размера буфера и буфера. Если он недостаточно велик для того, что в него поместит GetString, то переменная bufferSize модифицируется для того, чтобы указать, какой будет соответствующий размер. Затем вызывающая программа (C#) увеличивает размер буфера до соответствующего размера.

Если это экспортируемая функция dll (C++):

extern "C" __declspec void GetString( char* buffer, int* bufferSize );

Сопоставление с C# было бы следующим:

void GetString( StringBuilder buffer, ref int bufferSize );

Итак, чтобы использовать это в C#, вы бы сделали что-то вроде:

int bufferSize = 512;
StringBuilder buffer = new StringBuilder( bufferSize );
GetString( buffer, ref bufferSize );
18
ответ дан 1 December 2019 в 21:24
поделиться

Самая большая проблема с проходящими строками от C ++ назад к C # - это распределение памяти. GC должен уметь узнать, как очистить память, выделенную для этой строки. Поскольку C # имеет обширную поддержку COM-взаимодействия, она знает о COM BSTRS и как выделить и освободить их. Таким образом, самый простой способ сделать это было бы использовать BSTR на стороне C ++ и на строке на стороне C #.

Примечание, использование BSTRS не означает, что ваша функция должна быть выставлена ​​через COM.

2
ответ дан 1 December 2019 в 21:24
поделиться

Единственный хороший способ, которым я знаю это, состоит в том, чтобы написать класс Whitper .NET C ++ с использованием Управляемых расширений C ++ , а в объекте .NET C ++ Вызовите свой родной код C ++. Существуют функции в управляемых расширении для преобразования системы .String в Char * или любой другой тип неуправляемой строки.

В основном вы создаете класс .NET, используя C ++ и выставляем его из сборки, и внутри этой сборки вы можете позвонить в свой родной C ++. Другой способ состоит в том, чтобы добавить чистую C-функцию C ++, используя P / Invoke, а затем вызовите свой C-код из C #, и вы позвоните в C ++ C ++. Это будет работать, но я склонен в максимально возможной мере использовать управляемый код.

2
ответ дан 1 December 2019 в 21:24
поделиться

Возвращаемое значение "строка" является проблемой. Маршаллер P/Invoke будет вызывать CoTaskMemFree() на возвращаемом указателе. Это не сработает, если только вы не использовали CoTaskMemAlloc() в своем коде на языке Си/Си++ для выделения буфера "строка". Что довольно необычно.

Лучшее решение - позволить вызывающему абоненту вашего кода передать указатель на буфер и длину буфера в качестве аргументов. Таким образом, все выделение памяти происходит с одной стороны. Скотт показал, как это сделать.

2
ответ дан 1 December 2019 в 21:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: