I am writing a C# application in which it would call a DLL that was written in Delphi. I have the source code of Delphi DLL. I want to send a 2D array from C# to DLL and the DLL create开发者_如何学运维s another 2D array and send it back to C# code. How can I do this?
I've written you some sample code for 2D arrays. It's a bit messy because the marshaller won't naturally handle 2D arrays. Instead I've opted for flattening the arrays, i.e. marshall them as 1D arrays. This won't have great performance characteristics but perhaps that won't be significant for you. Only you can know that.
Delphi
library mydll;
var
arr: array of array of Double;
procedure ManagedToNative(RowCount, ColCount: Integer; Values: PDouble); stdcall;
var
r, c: Integer;
begin
SetLength(arr, RowCount, ColCount);
for r := 0 to RowCount-1 do begin
for c := 0 to ColCount-1 do begin
arr[r,c] := Values^;
inc(Values);
end;
end;
end;
procedure NativeToManaged(out RowCount, ColCount: Integer; Values: PDouble); stdcall;
var
r, c: Integer;
begin
RowCount := Length(arr);
if RowCount>0 then begin
ColCount := Length(arr[0]);
end else begin
ColCount := 0;
end;
if Assigned(Values) then begin
for r := 0 to RowCount-1 do begin
for c := 0 to ColCount-1 do begin
Values^ := arr[r,c];
inc(Values);
end;
end;
end;
end;
exports
ManagedToNative,
NativeToManaged;
begin
end.
C#
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
[DllImport(@"mydll.dll")]
private static extern void ManagedToNative(int RowCount, int ColCount, double[] Values);
[DllImport(@"mydll.dll")]
private static extern void NativeToManaged(out int RowCount, out int ColCount, double[] Values);
static double[] Flattened(int RowCount, int ColCount, double[,] arr)
{
double[] result = new double[RowCount*ColCount];
int i = 0;
for (int r = 0; r < RowCount; r++)
for (int c = 0; c < ColCount; c++)
{
result[i] = arr[r,c];
i++;
}
return result;
}
static double[,] Expanded(int RowCount, int ColCount, double[] arr)
{
double[,] result = new double[RowCount,ColCount];
int i = 0;
for (int r = 0; r < RowCount; r++)
for (int c = 0; c < ColCount; c++)
{
result[r,c] = arr[i];
i++;
}
return result;
}
static void Main(string[] args)
{
const int RowCount = 6;
const int ColCount = 9;
double[,] arr = new double[RowCount,ColCount];
for (int r = 0; r < RowCount; r++)
for (int c = 0; c < ColCount; c++)
arr[r,c] = r*c;
ManagedToNative(RowCount, ColCount, Flattened(RowCount, ColCount, arr));
int myRowCount, myColCount;
NativeToManaged(out myRowCount, out myColCount, null);
double[] flat = new double[myRowCount * myColCount];
NativeToManaged(out myRowCount, out myColCount, flat);
double[,] expanded = Expanded(myRowCount, myColCount, flat);
for (int r = 0; r < RowCount; r++)
for (int c = 0; c < ColCount; c++)
System.Console.WriteLine(arr[r, c] - expanded[r, c]);
}
}
}
The code passes a 2D array from C# to Delphi where it is stored. Then the C# code asks for it back. The WriteLine()
statements show that the same values are returned as were passed.
I have arranged for NativeToManaged()
to return the dimensions of the array even though this code already knows them. In reality your C# code is likely going to want to ask the Delphi code for the array size so that it can allocate memory in which to store the values.
I won't go on and on about why I've done certain things. From previous questions I think you have enough expertise to work it out from this code. If you do have any questions, leave a comment and I'll do my best to shed some light!
A function-call in the DLL out of C# is possible and you can pass parameters. Your 2D-array is a type or a class, this can be passed as parameter. Here is a good explanation how to call a Delphi-DLL out of C#:
http://tek-tips.com/faqs.cfm?fid=7416
This example passes "PChar" an other types to the DLL. You can pass pointers to your array also.
I think you can transmit the data in an format like xml or other and then deserialize in Delphi application or .NET
精彩评论