gpt4 book ai didi

c# - 重新创建 C# `Struct` 版本的 Delphi `Record` - 作为参数传递到 DLL

转载 作者:行者123 更新时间:2023-11-30 14:16:05 26 4
gpt4 key购买 nike

我正在 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 个字符的任何内容。是否有另一种我可以使用而不需要我使用 size of string 的类型?


问题第 2 部分:

我需要仔细检查我是否正确地声明了这个 C# 结构类,因为它需要与 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;

第一点是您不能期望 System.Drawing.Color 由 P/invoke 编码器处理。将颜色声明为 int 并使用 ColorTranslator.ToWin32ColorTranslator.FromWin32处理转换。


有了 PChar 就没什么好怕的了。您不需要具有字符串长度的字段,因为由于空终止符,长度在 PChar 中是隐含的。只需在 C# 结构中将字段声明为 string,在 Delphi 记录中将字段声明为 PChar,然后让 P/invoke 编码器发挥其魔力。不要尝试从 Delphi 写入 PChar 内容。那将以泪水告终。如果您想将字符串传递回 C# 代码,则有多种方法,但我不会在这里介绍它们。


拥有内联结构非常好。那里没什么可担心的。不要用 new 分配它们。只需将它们视为值类型(它们就是),如 intdouble 等。


在适当的时候,您将需要添加 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 标记 string 因为默认是将它编码为 LPSTR,这与Delphi 7 PChar

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

关于c# - 重新创建 C# `Struct` 版本的 Delphi `Record` - 作为参数传递到 DLL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8301455/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com