从C#调用Delphi DLL并传递位图和字节数组

Krz*_*nek 0 c# delphi interop bitmap marshalling

我试图用C#调用几个Delphi函数:

  MyType =array [1 .. 124] of byte
  procedure f(bytes: MyType); stdcall;
  external 'my.dll' name 'f';
Run Code Online (Sandbox Code Playgroud)

那是我的第一个问题.我试过了:

    [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); 
Run Code Online (Sandbox Code Playgroud)

我得到例外:

对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());
Run Code Online (Sandbox Code Playgroud)

我得到异常:尝试读取或写入受保护的内存.这通常表明其他内存已损坏.

这两种功能都是内存安全的,因为它们已经使用了几年而效果很好.也许有一些我想念的东西?

Rem*_*eau 6

您没有使用COM安全阵列,因此UnmanagedType.SafeArray无法使用.

为了使用UnmanagedType.LPArray,您必须将Delphi函数更改为:

procedure sygLadSyg(bytes: PByte); stdcall;
begin
  // use bytes as needed, but do not exceed 124 bytes...
end;
Run Code Online (Sandbox Code Playgroud)

然后将您的C#声明更改为:

DllImport("Delphi/my.dll",
    CallingConvention = CallingConvention.StdCall)]
public static extern
void sygLadSyg([MarshalAs(UnmanagedType.LPArray, SizeConst=124)] byte[] myArray);
Run Code Online (Sandbox Code Playgroud)

至于你的第二个问题,你的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;
Run Code Online (Sandbox Code Playgroud)

然后C#声明应该是:

[DllImport("Delphi/awSygnat1.dll",
    CallingConvention = CallingConvention.StdCall)]
public static extern
byte sygAnaliz(IntPtr bitmapPtr);
Run Code Online (Sandbox Code Playgroud)