C
C
Cyapa2014-02-25 12:51:47
Delphi
Cyapa, 2014-02-25 12:51:47

How to implement the export of functions from a C library in Delphi with an explicit DLL connection?

Greetings, comrades. I ask you not to rot me for using Delphi, but just to help a little.
The libcurl library has a function:

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

As you can see, it has a variable number of parameters. In order to export it from Delphi when the DLL is implicitly connected, there is a wonderful varargs directive.
function CURLEasySetOption
(
  Handle: PCURLHandle; 
  Option: TCURLOption
): TCURLCode; varargs; cdecl; external 'libcurl.dll' name 'curl_easy_setopt';

But, by chance, an implicit connection does not suit me (by the way, digressing from the topic, maybe someone knows how to set your dll search directory for an implicit connection?). So I have to do this:
var
  CURLEasySetOption: function
  (
    Handle: PCURLHandle; 
    Option: TCURLOption; 
    Parameter: Integer
  ): TCURLCode; cdecl;

implementation

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

With this declaration, varargs does not work, so I did not find anything better than using an integer for the parameter. Because of this, when calling a function, you have to constantly cast parameters to integer, which is very inconvenient. My solution to this problem was as follows:
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'));

What I wanted to achieve. But, in my opinion, it is somehow not beautiful. Perhaps there is a more elegant solution?
List of thoughts:
1. An implicit connection would also suit me if I could set my own DLL search directory for it (without resorting to edits in the registry and the system32 folder). It was possible to connect the DLL itself from where it was supposed to be by simply specifying the full path after external, but this did not satisfy the DLL dependencies (all the libraries on which it depends lie next to it).
2. It would be nice if you could somehow use varargs with this type of DLL connection. Or its counterparts, if any.
3. An untyped parameter would also work, but I only know how to declare it as var or const, which is unacceptable. Perhaps there is another way? (Variant doesn't work here)
4. Perhaps there is a way to force the compiler to cast types to Integer itself?

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question