Arhn - архитектура программирования

Как мне вызвать эту встроенную функцию dll из C #?

Вот собственная функция (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?

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


  • Единственный раз, когда я видел, как отладчик пропускает строки, когда этого не должно быть, - это когда скомпилированный код не соответствует источнику. Вы уверены, что привязываетесь к правильной версии сборки? 10.11.2009

Ответы:


1

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

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

10.11.2009
  • Спасибо, я был сбит с толку, потому что это действительно сработало - я подумал, может быть, приведение PChar делает что-то умное, например, выделение памяти. 10.11.2009
  • Можете ли вы указать мне на ресурс о том, как Windows API работает? Я не хочу заранее выделять буфер, потому что длина возвращаемой строки будет сильно различаться. 10.11.2009
  • Хорошо, я пробую такой подход: stackoverflow.com/questions/1699736/ 11.11.2009
  • Я не мог объяснить это лучше, чем Роб Кеннеди в своем ответе на связанный вопрос: stackoverflow.com/questions/ 1699736 /. Но есть еще кое-что, если вы ищете c # и dll в теге [delphi]. Вопрос в другом, но он всегда сводится к одному и тому же: не выделяйте и не освобождайте память в разных модулях, если вы не используете один и тот же диспетчер памяти (это невозможно с Delphi и C #). Используйте только базовые типы. И не возвращайте указатели на вещи, которые больше не действительны. 11.11.2009
  • Предварительно выделить буфер не проблема, если вы: а) объявляете максимальный размер возвращаемых строк (например, MAX_PATH) или б) используете двухэтапный алгоритм, при этом первый шаг возвращает только необходимый размер буфера, а второй - буфер не менее этого размера. Роб довольно хорошо это объясняет. 11.11.2009

  • 2

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

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

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

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

    10.11.2009
  • Ура, я посмотрю на это 10.11.2009
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..