我在 Delphi 代码中定义了以下函数:
procedure TestFLASHWNew(
name: array of string;
ID: array of Integer;
var d1:double
); stdcall;
我该如何定义并从C#中调用它?
这是一个有些混乱的P/Invoke,因为你不能(就我有限的知识而言)使用任何内置的易于编组技术。相反,您需要像这样使用Marshal.StructureToPtr
:
C#
[StructLayout(LayoutKind.Sequential)]
public struct MyItem
{
[MarshalAs(UnmanagedType.LPWStr)]
public string Name;
public int ID;
}
[DllImport(@"mydll.dll")]
private static extern void TestFLASHWNewWrapper(IntPtr Items, int Count, ref double d1);
static void Main(string[] args)
{
MyItem[] items = new MyItem[3];
items[0].Name = "JFK";
items[0].ID = 35;
items[1].Name = "LBJ";
items[1].ID = 36;
items[2].Name = "Tricky Dicky";
items[2].ID = 37;
IntPtr itemsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MyItem))*items.Length);
try
{
Int32 addr = itemsPtr.ToInt32();
for (int i=0; i<items.Length; i++)
{
Marshal.StructureToPtr(items[i], new IntPtr(addr), false);
addr += Marshal.SizeOf(typeof(MyItem));
}
double d1 = 666.0;
TestFLASHWNewWrapper(itemsPtr, items.Length, ref d1);
Console.WriteLine(d1);
}
finally
{
Marshal.FreeHGlobal(itemsPtr);
}
}
Delphi
TItem = record
Name: PChar;
ID: Integer;
end;
PItem = ^TItem;
procedure TestFLASHWNewWrapper(Items: PItem; Count: Integer; var d1: Double); stdcall;
var
i: Integer;
name: array of string;
ID: array of Integer;
begin
SetLength(name, Count);
SetLength(ID, Count);
for i := 0 to Count-1 do begin
name[i] := Items.Name;
ID[i] := Items.ID
inc(Items);
end;
TestFLASHWNew(name, ID, d1);
end;
我已经使用一个包装函数来调用你的TestFLASHWNew
函数,但你肯定想重新设计它。
我假设你正在使用带有Unicode字符串的Delphi。如果不是,请将[MarshalAs(UnmanagedType.LPWStr)]
更改为[MarshalAs(UnmanagedType.LPStr)]
。
string
不是Interop类型,它是原生的Delphi类型。而且Pascal开放数组也行不通。但双参数没问题!! - David Heffernan