Я попробовал разные вещи, но я рассердился с Interop.
(здесь последовательность слов не отнесена в тип variabile, но "набор символа"): у Меня есть неуправляемая функция C++, определенная в dll, к которому я пытаюсь получить доступ от C#, эта функция имеет строковый параметр и строковое возвращаемое значение как это:
string myFunction(string inputString)
{
}
Какова должна быть строка в стороне C++? и C# один? и каким параметрам нужен DllImport для этого?
Я нашел, что лучше всего работать, так это быть более откровенным о том, что здесь происходит. Наличие строки в качестве возвращаемого типа, вероятно, не рекомендуется в данной ситуации.
Распространенным подходом является передача на стороне С++ размера буфера и буфера. Если он недостаточно велик для того, что в него поместит 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 );
Самая большая проблема с проходящими строками от C ++ назад к C # - это распределение памяти. GC должен уметь узнать, как очистить память, выделенную для этой строки. Поскольку C # имеет обширную поддержку COM-взаимодействия, она знает о COM BSTRS и как выделить и освободить их. Таким образом, самый простой способ сделать это было бы использовать BSTR
на стороне C ++ и на строке
на стороне C #.
Примечание, использование BSTRS не означает, что ваша функция должна быть выставлена через COM.
Единственный хороший способ, которым я знаю это, состоит в том, чтобы написать класс Whitper .NET C ++ с использованием Управляемых расширений C ++ , а в объекте .NET C ++ Вызовите свой родной код C ++. Существуют функции в управляемых расширении для преобразования системы .String в Char * или любой другой тип неуправляемой строки.
В основном вы создаете класс .NET, используя C ++ и выставляем его из сборки, и внутри этой сборки вы можете позвонить в свой родной C ++. Другой способ состоит в том, чтобы добавить чистую C-функцию C ++, используя P / Invoke, а затем вызовите свой C-код из C #, и вы позвоните в C ++ C ++. Это будет работать, но я склонен в максимально возможной мере использовать управляемый код.
Возвращаемое значение "строка" является проблемой. Маршаллер P/Invoke будет вызывать CoTaskMemFree() на возвращаемом указателе. Это не сработает, если только вы не использовали CoTaskMemAlloc() в своем коде на языке Си/Си++ для выделения буфера "строка". Что довольно необычно.
Лучшее решение - позволить вызывающему абоненту вашего кода передать указатель на буфер и длину буфера в качестве аргументов. Таким образом, все выделение памяти происходит с одной стороны. Скотт показал, как это сделать.