Как я должен вызвать эту нативную функцию DLL из C #? - PullRequest
1 голос
/ 10 ноября 2009

Вот родная (Delphi 7) функция:

function Foo(const PAnsiChar input) : PAnsiChar; stdcall; export;
var
  s : string;
begin
    s := SomeInternalMethod(input);
    Result := PAnsiChar(s);
end;

Мне нужно вызвать это из C #, но имя dll не известно во время компиляции - поэтому я должен использовать LoadLibrary, чтобы добраться до него.

Вот так выглядит мой код на C #:

[DllImport("kernel32.dll")]
public extern static IntPtr LoadLibrary(String lpFileName);

[DllImport("kernel32.dll")]
public extern static IntPtr GetProcAddress(IntPtr handle, string funcName);

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate string FooFunction(string input);

...

IntPtr dllHandle = LoadLibrary(dllName);
IntPtr fooProcAddr = GetProcAddress(dllHandle, "Foo");

FooFunction foo = (FooFunction)Marshal.GetDelegateForFunctionPointer(
    fooProcAddr, typeof(FooFuncion)
);

string output = foo(myInputString);

Теперь это действительно работает - по крайней мере, код delphi правильно принимает строку, а код C # получает строку вывода.

Однако я заметил некоторую странность при отладке кода delphi, когда он вызывается из кода C # - отладчик пропускает строки, когда этого не должно быть.

И меня беспокоит, что у меня течет память - кто-нибудь чистит эти PChars?

Кто-нибудь может дать мне несколько отзывов / советов о том, как это должно быть сделано?

Ответы [ 2 ]

3 голосов
/ 10 ноября 2009

Единственная разумная вещь, которую вы можете сделать, это удалить эту функцию и переписать ее. Это никак не сработает. s - локальная строковая переменная функции Foo(), поэтому память, занимаемая строкой, будет освобождена при выходе из Foo(). Указатель, который вы возвращаете, указывает на недопустимую область памяти, которая случайно все еще содержит строковые данные. Если вы используете диспетчер памяти, который очищает память при освобождении указателей на нее, он больше не будет содержать данные. Если память используется повторно, она будет содержать что-то еще, если блок, содержащий этот фрагмент памяти, будет освобожден, вы получите AV.

В StackOverflow есть еще вопросы о том, как вернуть данные последовательности символов из DLL. Либо используйте строковый тип, который совместим с тем, как работает Windows API, строку COM, либо передайте предварительно выделенный буфер своей функции и заполните его данными. В последнем случае вы можете использовать тот же способ использования вашей функции, что и в любой подобной функции API.

2 голосов
/ 10 ноября 2009

Для обнаружения утечек памяти вы можете использовать менеджер с открытым исходным кодом FastMM4 для Delphi .

"FastMM - молниеносный менеджер замены памяти для Embarcadero Delphi Win32 приложения хорошо масштабируется в многопоточных приложения, не склонны к памяти фрагментация и поддерживает общий доступ память без использования внешних .DLL файлы. "

Отлично подходит для проверки скорости, утечки и совместного использования памяти между DLL.

Также очень полезен Интерфейс опций FastMM4 , который помогает настроить FastMM4.

...