Cyapa
@Cyapa

Как реализовать экспортирование функций из C библиотеки в Delphi при явном подключении DLL?

Приветствую, товарищи. Прошу не гнобить меня за использование Delphi, а просто немножечко помочь.

В библиотеке libcurl есть функция:

CURLcode curl_easy_setopt(CURL *curl, CURLoption option, parameter);


Как видно, она с переменным числом параметров. Для того, что бы экспортировать ее из Delphi при неявном подключении DLL есть замечательная директива varargs.

function CURLEasySetOption
(
  Handle: PCURLHandle; 
  Option: TCURLOption
): TCURLCode; varargs; cdecl; external 'libcurl.dll' name 'curl_easy_setopt';


Но, волею случая, мне неявное подключение не подходит (кстати, отвлекаясь от темы, может кто знает, как для неявного подключения задать свою директорию поиска dll?). Поэтому мне приходится делать так:

var
  CURLEasySetOption: function
  (
    Handle: PCURLHandle; 
    Option: TCURLOption; 
    Parameter: Integer
  ): TCURLCode; cdecl;

implementation

  CURLEasySetOption := GetProcAddress(DLLHandle, AnsiString('curl_easy_setopt'));


При таком объявлении varargs не работает, поэтому я не нашел ничего лучше как использовать integer для параметра. Из-за этого при вызове функции приходится постоянно приводить параметры к integer, что очень не удобно. Решение этой проблемы у меня вышло следующим:

function CURLEasySetOption
  (
    Handle: PCURLHandle; 
    Option: TCURLOption; 
    Parameter: Integer
  ): TCURLCode; overload;
  function CURLEasySetOption
  (
    Handle: PCURLHandle; 
    Option: TCURLOption; 
    Parameter: Boolean
  ): TCURLCode; overload;
  function CURLEasySetOption
  (
    Handle: PCURLHandle; 
    Option: TCURLOption; 
    Parameter: Pointer
  ): TCURLCode; overload;

var
  CURLEasySetOptionExternal: function
  (
    Handle: PCURLHandle; 
    Option: TCURLOption; 
    Parameter: Integer
  ): TCURLCode; cdecl;

implementation

  function CURLEasySetOption
  (
    Handle: PCURLHandle; 
    Option: TCURLOption; 
    Parameter: Integer
  ): TCURLCode;
  begin
    Result := CURLEasySetOptionExternal(Handle, Option, Parameter);
  end;

  function CURLEasySetOption
  (
    Handle: PCURLHandle; 
    Option: TCURLOption; 
    Parameter: Boolean
  ): TCURLCode;
  begin
    Result := CURLEasySetOptionExternal(Handle, Option, Integer(Parameter));
  end;

  function CURLEasySetOption
  (
    Handle: PCURLHandle; 
    Option: TCURLOption; 
    Parameter: Pointer
  ): TCURLCode;
  begin
    Result := CURLEasySetOptionExternal(Handle, Option, Integer(Parameter));
  end;

...

  CURLEasySetOptionExternal := GetProcAddress(DLLHandle, AnsiString('curl_easy_setopt'));


Чего хотел я добился. Но, на мой взгляд, это как-то не красиво. Возможно есть более элегантное решение?

Список мыслей:
1. Мне бы подошло и неявное подключение, если бы для него можно было задать свою директорию поиска DLL (не прибегая к правкам в реестре и папке system32). Саму DLL подключить от туда, откуда было надо удалось простым указанием полного пути после external, но вот зависимости DLL это не удовлетворило (все библиотеки от которых она зависит лежат рядом с ней).
2. Было бы чудно, если бы можно было как-то использовать varargs при таком типе подключения DLL. Или его аналоги, если они есть.
3. Нетипизированный параметр тоже бы подошел, но вот только я знаю способы его объявления как var или const, что неприемлемо. Возможно есть другой путь? (Variant тут не проходит)
4. Возможно, есть способ заставить компилятор приводить типы к Integer самостоятельно?
  • Вопрос задан
  • 3342 просмотра
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы