У вас явно есть несоответствие между кодом p / invoke и кодом Delphi.Вы не показали код Delphi, но кода C # достаточно, чтобы знать, как должен выглядеть код Delphi.
Ваш атрибут DllImport
использует значения по умолчанию для соглашения о вызовах и набора символов.Это означает, что соглашение о вызовах stdcall
, а набор символов - ANSI.Вы не указали никаких атрибутов маршаллинга, поэтому необходимо использовать маршаллинг по умолчанию.
Поэтому ваш код Delphi должен выглядеть следующим образом:
function MyMethod(someStringParam: PChar): PChar; stdcall;
begin
Result := ??;
end;
А теперь вот проблема.Маршаллер p / invoke обрабатывает возвращаемое значение string
совершенно особым образом.Предполагается, что маршаллер p / invoke отвечает за освобождение памяти возвращаемого значения.И он должен использовать тот же распределитель, что и нативный код.Предположение, сделанное маршаллером, заключается в том, что будет использоваться общий распределитель COM.
Таким образом, правило состоит в том, что собственный код должен распределять память с помощью распределителя COM, вызывая CoTaskMemAlloc
.Держу пари, что ваш код этого не делает, и это, безусловно, приведет к ошибкам.
Вот пример того, как вы можете создать встроенную функцию Delphi, которая работает с сигнатурой C # в вашем коде.
function MyMethod(someStringParam: PChar): PChar; stdcall;
var
Size: Integer;
begin
Size := SizeOf(Char)*(StrLen(someStringParam)+1);//+1 for zero-terminator
Result := CoTaskMemAlloc(Size);
Move(someStringParam^, Result^, Size);
end;
Хотя вы могли бы принять этот подход, я рекомендую альтернативу.Маршал все ваши строки как BSTR
на стороне C # и WideString
на стороне Delphi.Это совпадающие типы, которые также выделяются распределителем COM.Обе стороны точно знают, что делать с этими типами, и облегчат вашу жизнь.
К сожалению, вы не можете вернуть WideString
из функции Delphi через границу взаимодействия, потому что Delphi использует другой ABI для возвращаемых значений функции.Более подробную информацию об этой проблеме можно найти в моем вопросе Почему WideString не может использоваться как возвращаемое значение функции для взаимодействия?
Поэтому, чтобы обойти это, мы можем объявить тип возвратаиз кода Delphi будет TBStr
.Ваш код будет выглядеть следующим образом:
C #
[DllImport(@"MyDll.dll")]
[return: MarshalAs(UnmanagedType.BStr)]
private static extern string MyMethod(
[MarshalAs(UnmanagedType.BStr)]
string someStringParam
);
Delphi
function MyMethod(someStringParam: WideString): TBStr; stdcall;
begin
Result := SysAllocString(POleStr(someStringParam));
end;