devployment
devployment

Reputation: 2201

How to pass a string array to an external DLL?

I have an external function like this:

extern "C" __declspec(dllexport) int __cdecl Identify(BSTR* bstrTemplates, __int64 lCount, __int64* lIndex, __int64* lRetCode) 

The bstrTemplates should be a string array.

How should my function look like in D7, and how to pass a string array to the external function. Can't get my head around right now.

Upvotes: 3

Views: 3398

Answers (3)

devployment
devployment

Reputation: 2201

Finally solved the problem. It was the dynamic array. Looks like it can't be used as C-style array. Looks like the length prefix confused the c dll. For the records here the prototype and usage:

Type

type
  TArrayOfWideString= array[0..999] of WideString;

Declaration

function Identify(var ATemplates: TArrayOfWideString; ATemplatesCount: int64; var ATemplateIndex: int64; var ARetCode: int64): Integer; cdecl; external 'Identify.dll';

Usage

var
  templateIndex, retCode: int64;
  templates: TArrayOfWideString;
  retval: integer;

//TODO: range checking for TArrayOfWideString needed

templates[0] := 'template1';
templates[1] := 'template2';

retVal := Identify(templates, 2, scanIndex, retCode);

Upvotes: 2

Remko
Remko

Reputation: 7330

BSTR* is a pointer to a BSTR (in Delphi BSTR is a WideString).

EDIT: To make the answer complete (and make Rob Kennedy happy :-) ):

Most literal translation:

function Identify(bstrTemplates: PWideString; lCount: int64; lIndex: PInt64; lRetCode: PInt64): Integer; cdecl external 'mydll.dll';

or more the Delphi way:

function Identify(bstrTemplates: PWideString; lCount: int64; var lIndex: Int64; var lRetCode: Int64): Integer; cdecl external 'mydll.dll';

or even (but this depends if the bstrTemplates can be nil):

function Identify(var bstrTemplates: WideString; lCount: int64; var lIndex: Int64; var lRetCode: Int64): Integer; cdecl external 'mydll.dll';

Use the first element in the array when you pass bstrTemplates (eg @MyArray[0])

Upvotes: 1

Lasse V. Karlsen
Lasse V. Karlsen

Reputation: 391336

A BSTR is a WideString in Delphi, and a pointer to a BSTR is also a pointer to a WideString in Delphi, but in terms of C-code, it is most likely an array reference. A typical way to handle such arrays, and I'm going to assume this is how it's done here, is to use a null-terminated array.

So, we need to declare an array of WideString's in Delphi, and leave the last element as null, or nil in Delphi:

var
  templates : array of WideString;
begin
  SetLength(templates, 3); // 2 template names + 1 nil
  templates[0] := 'template1';
  templates[1] := 'template2';
  templates[2] := nil;

  Identify(@templates[0], ....); // pass it as a pointer to the first element

I'm not guaranteeing this will work. I'm guessing here, and haven't tried it (which would involve creating a C project and testing) so this might fail horribly. Worth a shot though.

Upvotes: 3

Related Questions