2011-05-05 5 views
8

Przeczytałem na tej stronie, że tablice dynamiczne potrzebują jednostki ShareMem do poprawnego działania.Jak przekazać dynamiczną tablicę ciągów do biblioteki dll (dll i klienta zapisanej w d7) bez jednostki ShareMem?

Jednak chciałbym napisać bibliotekę dll otwartą dla innych języków.

Czy ktoś może mi powiedzieć, w jaki sposób mogę zadeklarować funkcję i jej parametry do przekazania tablicy String?

Czy naprawdę coś takiego nie jest dozwolone bez udziału ShareMem?

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

Dzięki za pomoc!

+1

@ user740144, nie zapomnij, aby zadeklarować swoje funkcje eksportowane/procs jako 'stdcall' jeśli chcesz użyć tej biblioteki dll z klientami innymi niż delphi. – Johan

+0

@Johan Możesz użyć 'stdcall' lub' cdecl'. 'stdcall' będzie nieco standardem w systemie Windows, ale' cdecl' może również mieć sens. Konwencja '__fastcall' nie jest tak standardowa. –

Odpowiedz

6

Dynamiczna tablica ciągów jest już tablicą PWideChar/PAnsiChar (dla WideString or UnicodeString/AnsiString).

Ta dynamiczna tablica może być bezpośrednio odwzorowane jak jest, bez kopii pamięci, z większości języków, w postaci tablicy PWideChar/PAnsiChar:

Od rozmówcy:

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

Od 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; 

Na przykład z biblioteki dll C można użyć char **argv zamiast PPAnsiCharArray i void **argv zamiast PPWideCharArray.

Następnie można z łatwością przekonwertować z powrotem PWideChar/PAnsiChar na macierzysty typ napisu w tym języku.

Jeśli trzeba tylko napisać DLL Delphi, można użyć

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; 

lub nawet

DLLFunction(templates); 

procedure DLLFunction(const templates: array of WideString); 
var i: integer; 
begin 
    for i := 0 to high(templates) do 
    writeln(templates[i]); 
end; 
+0

Więc jeśli rozumiem, mogę bez obaw użyć kodu z mojego postu i pobrać tablicę tak, jak napisałeś w bibliotece dll? – user740144

+0

Dziękujemy za rozwiązanie! – user740144

+1

Teraz widzę, że moja odpowiedź dotyczyła przesyłania danych w inny sposób. Ale nie zależy mi na tym, by polegać na szczegółach implementacji otwartych tablic. To jest trochę hacky według mnie. –