How to import a function from a DLL made in Delphi

2019-04-16 00:06发布

问题:

Can you tell me how do i use the following functions in my C program.

Delphi DLL - Exported functions :

function GetCPUID (CpuCore: byte): ShortString; stdcall;
function GetPartitionID(Partition : PChar): ShortString; stdcall;

I don't have the source code for that DLL so I must adapt my C program to that DLL and not the other way around.

I do the following and get error

typedef char* (_stdcall *GETCPUID)(BYTE);
typedef char* (_stdcall *GETPID)(PCHAR);
GETCPUID pGetSerial;
GETPID pGetPID

HMODULE hWtsLib = LoadLibrary("HardwareIDExtractor.dll");
if (hWtsLib){
pGetSerial = (GETCPUID)GetProcAddress(hWtsLib, "GetCPUID");
char *str = (char*) malloc(1024);
str = pGetSerial((BYTE)"1");

pGetPID= (GETPID )GetProcAddress(hWtsLib, "GetPartitionID");
char *str1 = (char*) malloc(1024);
str1 = pGetPID("C:");
}

Thanks

回答1:

Since you don't have the source to the DLL, you'll need to get a little creative on the C side of things. Even though the ShortString is listed as the function result, it is actually the responsibility of the caller to provide a location in which to place the result. Because this is a stdcall function, parameters are passed in from right to left, so that means that the address of the ShortString result is passed in last. To get this to line up, it will need to the first parameter listed. I'll do the first API, GetCPUID. In C, it might look something like this:

typedef struct ShortString {
  char len;
  char data[255];
};
typedef void (_stdcall *GETCPUID)(struct ShortString *result, BYTE cpuCore);

GETCPUID pGetSerial;

HMODULE hWtsLib = LoadLibrary("HardwareIDExtractor.dll");
if (hWtsLib) {
  ShortString serial;
  pGetSerial = (GETCPUID)GetProcAddress(hWtsLib, "GetCPUID");
  pGetSerial(&serial, '1');
  char *str = malloc(serial.len + 1); // include space for the trailing \0
  strlcpy(str, serial.data, serial.len);
  str[serial.len] = '\0'; // drop in the trailing null
}

I'll leave the GetPartitionID as an exercise for the reader :-).



回答2:

ShortString is not the same as PChar (char *). It is an array of char with the first char being the length of the string. For C it is best you use PChar (char *) all the way.

procedure GetCPUID (CpuCore: byte; CpuId: PChar; Len: Integer); stdcall;
procedure GetPartitionID(Partition : PChar; PartitionId: PChar; Len: Integer); stdcall;

typedef (_stdcall *GETCPUID)(BYTE, char*, int);
typedef (_stdcall *GETPID)(PCHAR, char*, int);
GETCPUID pGetSerial;
GETPID pGetPID

HMODULE hWtsLib = LoadLibrary("HardwareIDExtractor.dll");
if (hWtsLib){
pGetSerial = (GETCPUID)GetProcAddress(hWtsLib, "GetCPUID");
char *str = (char*) malloc(1024);
pGetSerial((BYTE)"1", str, 1024);

pGetPID= (GETPID )GetProcAddress(hWtsLib, "GetPartitionID");
char *str1 = (char*) malloc(1024);
pGetPID("C:", str, 1024);