2011-05-05 4 views
8

Tôi đã đọc trên trang này rằng mảng động cần đơn vị ShareMem hoạt động bình thường.Làm thế nào để vượt qua mảng động của chuỗi vào một thư viện dll (dll và khách hàng được viết bằng d7) mà không có đơn vị ShareMem?

Tuy nhiên tôi muốn viết một dll mở cho các ngôn ngữ khác.

Bất cứ ai có thể cho tôi biết làm thế nào tôi có thể khai báo hàm và các tham số của nó để truyền mảng String?

Thực sự không giống như điều này không được phép mà không có ShareMem?

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

Cảm ơn bạn đã trợ giúp!

+1

@ user740144, Đừng quên khai báo chức năng/procs xuất khẩu của bạn là 'stdcall' nếu bạn muốn sử dụng nó dll với khách hàng không delphi. – Johan

+0

@Johan Bạn có thể sử dụng 'stdcall' hoặc' cdecl'. 'stdcall' sẽ hơi tiêu chuẩn trong Windows, nhưng' cdecl' cũng có thể có ý nghĩa. Quy ước '__fastcall' không chuẩn. –

Trả lời

6

Mảng chuỗi động đã là một mảng của PWideChar/PAnsiChar (đối với WideString or UnicodeString/AnsiString).

mảng động này có thể được ánh xạ trực tiếp như là, không có bản sao bộ nhớ, từ hầu hết các ngôn ngữ, như là một mảng của PWideChar/PAnsiChar:

Từ người gọi:

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

Từ 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; 

Ví dụ: từ dll C, bạn có thể sử dụng char **argv thay vì PPAnsiCharArrayvoid **argv thay vì PPWideCharArray.

Sau đó, bạn có thể dễ dàng chuyển đổi lại PWideChar/PAnsiChar thành loại chuỗi gốc của ngôn ngữ.

Nếu bạn chỉ cần phải viết một dll Delphi, bạn có thể sử dụng

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; 

hoặc thậm chí

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

Vì vậy, nếu tôi hiểu, tôi có thể sử dụng mà không phải lo lắng mã từ bài đăng của tôi, và lấy mảng giống như bạn đã viết trong một dll? – user740144

+0

Cảm ơn bạn đã giải pháp! – user740144

+1

Tôi có thể thấy rằng câu trả lời của tôi là gửi dữ liệu theo cách khác. Nhưng tôi không quan tâm đến sự phụ thuộc của bạn vào chi tiết thực hiện của các mảng mở. Đó là một chút hacky trong quan điểm của tôi. –