Подтвердить что ты не робот

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

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

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

string myFunction(string inputString)
{
}

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

4b9b3361

Ответ 1

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

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

Если это ваша экспортированная DLL-функция (С++):

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

Соответствие С# будет следующим:

void GetString( StringBuilder buffer, ref int bufferSize );

Итак, чтобы использовать это в С#, вы должны сделать что-то вроде следующего:

int bufferSize = 512;
StringBuilder buffer = new StringBuilder( bufferSize );
GetString( buffer, ref bufferSize );

Ответ 2

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

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

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

Мне пришлось преобразовать строку Unicode С# в многобайтовое представление, чтобы преобразовать в char * в С++ (это частичное одностороннее решение)

Я нашел следующие очень полезные

string st; 
IntPtr stPtr = Marshal.StringToHGlobalAnsi(st); 
// Do your thing in C++ 

Marshal.FreeHGlobal(stPtr); 

Это может быть неэффективным, а не способом С#, я новичок в С#, надеюсь, что это поможет