Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass dynamic array of string to a dll library (dll and client written in d7) without ShareMem Unit?

I've read on this page that dynamic arrays need ShareMem unit to work properly.

However I would like to write a dll open for other languages.

Could anyone tell me how can I declare the function and its parameters to pass array of String?

Isn't really something like this not allowed without ShareMem?

var
  templates : array of WideString;
begin
  SetLength(templates, 2); 
  templates[0] := 'template1';
  templates[1] := 'template2';
end
DLLFunction(@templates[0]); 

Thanks for help!

like image 390
user740144 Avatar asked May 05 '11 15:05

user740144


1 Answers

A dynamic array of strings is already an array of PWideChar/PAnsiChar (for WideString or UnicodeString/AnsiString).

This dynamic array can be directly mapped as is, with no memory copy, from most languages, as an array of PWideChar/PAnsiChar:

From caller:

DLLFunction(length(templates),pointer(templates)); 

From dll:

type
  TPAnsiCharArray = array[0..MaxInt div SizeOf(PAnsiChar)-1] of PAnsiChar;
  PPAnsiCharArray = ^TPAnsiCharArray;
  TPWideCharArray = array[0..MaxInt div SizeOf(PWideChar)-1] of PWideChar;
  PPWideCharArray = ^TPWideCharArray;

procedure DLLFunction(argc: integer; argv: PPWideCharArray);
var i: integer;
begin
  for i := 0 to argc-1 do
    writeln(argv[i]);
end;

From a C dll for instance, you can use char **argv instead of PPAnsiCharArray and void **argv instead of PPWideCharArray.

Then you can easily convert back the PWideChar/PAnsiChar into the native string type of the language.

If you need only to write a Delphi dll, you can use

type
  TAnsiStringArray = array[0..MaxInt div SizeOf(AnsiString)-1] of AnsiString;
  PAnsiStringArray = ^TAnsiStringArray;
  TWideStringArray = array[0..MaxInt div SizeOf(WideString)-1] of WideString;
  PWideStringArray = ^TWideStringArray;

procedure DLLFunction(argc: integer; argv: PWideStringArray);
var i: integer;
begin
  for i := 0 to argc-1 do
    writeln(argv[i]);
end;

or even

DLLFunction(templates);

procedure DLLFunction(const templates: array of WideString);
var i: integer;
begin
  for i := 0 to high(templates) do
    writeln(templates[i]);
end;
like image 89
Arnaud Bouchez Avatar answered Sep 28 '22 02:09

Arnaud Bouchez