Jer*_*dge 3 c# delphi pinvoke delphi-7
我正在使用Delphi构建DLL,它需要与Windows API的工作方式类似.这个DLL只有一个导出函数......
function DoSomething(var MyRecord: TMyRecord): Integer; stdcall;
Run Code Online (Sandbox Code Playgroud)
... where TMyRecord=我的记录我需要在C#中重新创建.如果我没有弄错,这正是标准Windows API的工作原理.此记录还包含对另一种记录类型的引用...
TMyOtherRecord = record
SomeDC: HDC;
SomeOtherInt: Integer;
end;
TMyRecord = record
SomeInteger: Integer;
SomeColor: TColor;
SomeText: PChar;
SomeTextSize: Integer;
MyOtherRecord: TMyOtherRecord;
end;
Run Code Online (Sandbox Code Playgroud)
问题第1部分:
我想看看我是否可以避免使用PChar,如果可能的话.我不希望传递超过255个字符的内容.是否有其他类型我可以使用而不需要我使用size of string?
问题第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();
}
Run Code Online (Sandbox Code Playgroud)
问题第3部分:
在这种情况下,在记录(或结构内部的结构)中有记录是否安全?很确定它是,但我需要确定.
我将假设信息从C#流向Delphi而不是其他方式,主要是因为这样可以在编写答案时更轻松地生活,而您没有说明其他情况!
在这种情况下,Delphi函数声明应该是:
function DoSomething(const MyRecord: TMyRecord): Integer; stdcall;
Run Code Online (Sandbox Code Playgroud)
第一点是你不能期望System.Drawing.Color由P/invoke marshaller处理.将颜色声明为int并使用ColorTranslator.ToWin32和ColorTranslator.FromWin32处理转换.
没有什么可以害怕的PChar.您不需要具有字符串长度的字段,因为PChar由于null终止符,长度隐含在a中.只需在Delphi记录中声明stringC#结构中的字段PChar,让P/invoke marshaller发挥其魔力.不要试图写入PCharDelphi 的内容.那将以泪水结束.如果你想将一个字符串传递给C#代码,那么有一些方法,但我不会在这里解决它们.
内联结构完全没问题.没有什么可担心的.不要分配它们new.只需将它们视为值类型(它们是)int,double等等.
在适当的时候,您将需要添加StructLayout属性等,声明您的DLL函数DllImport等等.
总而言之,我会声明你的结构如下:
德尔福
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;
Run Code Online (Sandbox Code Playgroud)
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);
Run Code Online (Sandbox Code Playgroud)
我没有string用a 标记,MarshalAs因为默认是将它编组为LPSTR与Delphi 7相同的PChar.
我只是在脑海里编了这个,所以可能会有一些皱纹.