从 C# 调用 Delphi DLL 并传递位图和字节数组
本文关键字:位图 字节 字节数 数组 调用 Delphi DLL | 更新日期: 2023-09-27 18:36:04
我正在尝试从C#调用一些Delphi函数:
MyType =array [1 .. 124] of byte
procedure f(bytes: MyType); stdcall;
external 'my.dll' name 'f';
这是我的第一个问题。我试过:
[DllImport("Delphi/my.dll",
CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Auto)]
public static extern
void sygLadSyg([MarshalAs(UnmanagedType.LPArray)] byte[] myArray);
void sygLadSyg([MarshalAs(UnmanagedType.SafeArray)] byte[] myArray);
我得到例外:
对 PInvoke 函数的调用使堆栈不平衡。这可能是因为托管 PInvoke 签名与非托管目标签名不匹配。检查 PInvoke 签名的调用约定和参数是否与目标非托管签名匹配。
我做错了什么?
第二个问题是传递位图。
function sygAnaliz(bitmapa: TBitmap): byte; stdcall;
external 'awSygnat1.dll' name 'sygAnaliz';
[DllImport("Delphi/awSygnat1.dll",
CallingConvention = CallingConvention.StdCall,
CharSet = CharSet.Ansi)]
public static extern
byte sygAnaliz(IntPtr bitmapPtr);
// and call itself
sygAnaliz(firstIMG.GetHbitmap());
我得到例外:已尝试读取或写入受保护的内存。这通常表示其他内存已损坏。
这两个功能肯定是内存安全的,因为它们已经使用了几年,效果很好。也许我错过了一些明显的东西?
您没有使用 COM 安全数组,因此UnmanagedType.SafeArray
不起作用。
为了使用UnmanagedType.LPArray
,您必须将Delphi函数更改为:
procedure sygLadSyg(bytes: PByte); stdcall;
begin
// use bytes as needed, but do not exceed 124 bytes...
end;
然后将 C# 声明更改为以下内容:
DllImport("Delphi/my.dll",
CallingConvention = CallingConvention.StdCall)]
public static extern
void sygLadSyg([MarshalAs(UnmanagedType.LPArray, SizeConst=124)] byte[] myArray);
至于你的第二个问题,你的Delphi函数接受VCL TBitmap
对象作为输入,但C#没有这个概念。 它传递的是 Win32 HBITMAP
句柄,因此您需要相应地更改 Delphi 函数。 它可以在内部创建一个临时TBitmap
对象,并将HBITMAP
分配给其Handle
属性:
function sygAnaliz(bitmapa: HBITMAP): byte; stdcall;
var
Bmp: TBitmap;
begin
try
Bmp := TBitmap.Create;
try
Bmp.Handle := bitmapa;
// use Bmp as needed...
finally
Bmp.Free;
end;
Result := ...;
except
Result := ...;
end;
end;
然后 C# 声明应该是:
[DllImport("Delphi/awSygnat1.dll",
CallingConvention = CallingConvention.StdCall)]
public static extern
byte sygAnaliz(IntPtr bitmapPtr);