Ответ 1
Ваш маршаллинг выходной строки неверен. Использование string
в объявлении p/invoke целесообразно при передаче данных от управляемого к собственному. Но вы не можете использовать это, когда данные перемещаются в другом направлении. Вместо этого вам нужно использовать StringBuilder
. Как это:
[DllImport(...)]
public static extern int my_Funct(string input, StringBuilder output);
Затем выделите память для вывода:
StringBuilder output = new StringBuilder(256);
//256 is the capacity in characters - only you know how large a buffer is needed
И тогда вы можете вызвать функцию.
int retval = my_Funct(inputStr, output);
string outputStr = output.ToString();
С другой стороны, если эти параметры содержат нулевые символы, вы не можете использовать маршал как строку. Это потому, что маршаллер не будет ничего маршалировать после нуля. Вместо этого вам нужно упорядочить его как массив байтов.
public static extern int my_Funct(
[In] byte[] input,
[Out] byte[] output
);
Это соответствует вашей декларации C
Затем, предполагая кодировку ANSI, вы конвертируете входную строку в байтовый массив следующим образом:
byte[] input = Encoding.Default.GetBytes(inputString);
Если вы хотите использовать другую кодировку, очевидно, как это сделать.
И для вывода вам нужно выделить массив. Предполагая, что это та же длина, что и для ввода, вы сделаете это:
byte[] output = new byte[input.Length];
И как-то ваша функция C узнала длину массивов. Я оставлю это вам!
Затем вы можете вызвать функцию
int retval = my_Funct(input, output);
А затем, чтобы преобразовать выходной массив обратно в строку С#, вы снова используете класс Encoding
.
string outputString = Encoding.Default.GetString(output);