重新创建Delphi`Record`的C#`Struct`版本 – 作为参数传入DLL

我正在使用Delphi构建DLL,它需要与 Windows API的工作方式类似.这个DLL只有一个导出函数……

function DoSomething(var MyRecord: TMyRecord): Integer; stdcall;

…其中TMyRecord =我的记录我需要在C#中重新创建.如果我没有弄错,这正是标准Windows API的工作原理.此记录还包含对另一种记录类型的引用…

TMyOtherRecord = record
  SomeDC: HDC;
  SomeOtherInt: Integer;
end;

TMyRecord = record
  SomeInteger: Integer;
  SomeColor: TColor;
  SomeText: PChar;
  SomeTextSize: Integer;
  MyOtherRecord: TMyOtherRecord;
end;

问题第1部分:

我想看看我是否可以避免使用PChar,如果可能的话.我不希望传递超过255个字符的内容.是否有其他类型我可以使用而不需要我使用字符串大小?

问题第2部分:

我需要仔细检查我是否正确地声明了这个C#struct类,因为它需要完全匹配Delphi中声明的Record …

public struct MyOtherRecord
{
  public IntPtr SomeDC;
  public int SomeOtherInt;
}

public struct MyRecord
{
  public int SomeInteger;
  public Color SomeColor;
  public string SomeText;
  public int SomeTextSize;
  public MyOtherRecord OtherReord = new MyOtherRecord();
}

问题第3部分:

在这种情况下,在记录(或结构内部的结构)内部记录是否安全?很确定它是,但我需要确定.

解决方法

我将假设信息从C#流向Delphi而不是其他方式,主要是因为这样在写答案时会让生活变得更轻松,而你没有说明其他情况!

在这种情况下,Delphi函数声明应该是:

function DoSomething(const MyRecord: TMyRecord): Integer; stdcall;

第一点是你不能指望P / invoke marshaller处理System.Drawing.Color.将颜色声明为int并使用ColorTranslator.ToWin32ColorTranslator.FromWin32来处理转换.

PChar没什么好害怕的.您不需要具有字符串长度的字段,因为由于空终止符,长度隐含在PChar中.只需在C#结构中将字段声明为字符串,在Delphi记录中将PChar声明,并让P / invoke marshaller发挥其魔力.不要试图从Delphi写入PChar内容.那将以泪水结束.如果你想将一个字符串传递给C#代码,那么有一些方法,但我不会在这里解决它们.

内联结构完全没问题.没有什么可担心的.不要用新的分配它们.只需将它们视为值类型(它们是),如int,double等.

在适当的时候,您将需要添加StructLayout属性等,使用DllImport声明您的DLL函数,依此类推.

总而言之,我会声明你的结构如下:

德尔福

TMyOtherRecord = record
  SomeDC: HDC;
  SomeOtherInt: Integer;
end;

TMyRecord = record
  SomeInteger: Integer;
  SomeColor: TColor;
  SomeText: PChar;
  MyOtherRecord: TMyOtherRecord;
end;

function DoSomething(const MyRecord: TMyRecord): Integer; stdcall;

C#

[StructLayout(LayoutKind.Sequential)]
public struct MyOtherRecord
{
  public IntPtr SomeDC;
  public int SomeOtherInt;
}

[StructLayout(LayoutKind.Sequential)]
public struct MyRecord
{
  public int SomeInteger;
  public int SomeColor;
  public string SomeText;
  public MyOtherRecord MyOtherRecord;
}

[DllImport("mydll.dll")]
static extern int DoSomething([In] ref MyRecord MyRecord);

我没有使用MarshalAs标记字符串,因为默认情况下将其编组为LPSTR,它与Delphi 7 PChar相同.

我只是在脑海里编了这个,所以可能会有一些皱纹.

相关文章

 从网上看到《Delphi API HOOK完全说明》这篇文章,基本上都...
  从网上看到《Delphi API HOOK完全说明》这篇文章,基本上...
ffmpeg 是一套强大的开源的多媒体库 一般都是用 c/c+&#x...
32位CPU所含有的寄存器有:4个数据寄存器(EAX、EBX、ECX和ED...
1 mov dst, src dst是目的操作数,src是源操作数,指令实现的...