gpt4 book ai didi

c# - 从 C# 将 Delphi 集传递给外部 Delphi 函数

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

我正在尝试从 C# 调用外部 Delphi 函数,该函数将 Delphi 集作为参数:

德尔福代码

type
tStatus = (sIn, sOut, sAbsent, sSick);
tStatusSet = set of tStatus;

function LoadEmployees(tStatusSet aStatusSet): tEmpList;

我需要将枚举值的 C# 数组(即 tStatus 中的元素)编码为 Delphi 将读取为 tStatusSet 类型的格式:

C#代码

tStatusSet lStatusSet = ConvertToDelphiSet(sIn, sOut);

tEmpList lEmpList = LoadEmployees(aStatusSet);

ConvertToDelphiSet 理想情况下应该是一个通用的解决方案,能够处理任何枚举。我们将其定义为:

int ConvertToDelphiSet<T>(params T[] aArgs) {
int lResult = 0;

foreach (T lItem in aArgs)
{
int lValue = lItem.ToInt32();
lValue = (int)Math.Pow(2, lValue);

lResult |= lValue;
}

但这并没有返回正确的值(例如,将所有四个 tStatus 值传递给它会导致 Delphi 只看到集合中的第三个值)。

是否有关于 Delphi 内部如何表示集合的文档?它是所有值的简单位域吗?有没有更强大的方法来实现这一目标?这是 future 的证明,还是我依赖​​可能会发生变化的未记录的内部功能?

最佳答案

我相信这是一个位域,但可能不是您所说的“简单”。

一个 Delphi 集最多可以有 256 个元素,或者值最多为 255 的元素,这可能不一定是同一件事,因为枚举成员可以被分配特定的值并且不一定是连续的,例如:

  TEnum = (a, b, c=255);
TSet = set of TEnum;

导致 TSet 的最大可能大小为 256 位,即使它只有 3 个可能的成员。 (注意成员“a”的值为 0,而不是 1!)

如果你在你的集合类型或该类型的变量上使用 sizeof() 函数,你可以看到这一点,它将指示该类型或变量占用多少字节的存储空间。

  TEnum = (a, b, c=255);
TSet = set of TEnum;

>>> sizeof(TSet) = 32


TEnum = (a, b, c);
TSet = set of TEnum;

>>> sizeof(TSet) = 1

您设计的任何依赖于 Delphi 集类型的内部存储的机制都将变得脆弱,并且需要您在 C# 和 Delphi 中定义匹配的枚举类型,但不能轻易/可靠地识别为已下降不同步。

如果这是一个实际问题,那么我建议您改为将您的值作为枚举成员 names 的数组传递,并在 Delphi 中使用 RTTI 通过转换枚举名称到相应的枚举值,并根据需要将它们添加到您的集合中(如果指定了无效的枚举成员名称,-1 将作为枚举值从 GetEnumValue 返回):

  enumValue := TEnum( GetEnumValue(TypeInfo(TEnum), sEnumMemberName) );
if Ord(enumValue) = -1 then
raise Exception.Create('Invalid enum value' + sEnumMemberName);

Include(setVar, enumValue);

GetEnumValue() 和相应的 GetEnumName() 函数是 TypInfo 单元的一部分。

通过这种方式,您将能够检测并处理 C# 代码指定了 Delphi 代码无法识别的枚举值(按名称)的情况(当然反之亦然),其方式可能是在对任意 n 字节存储 block 中的匿名位做出假设时不太可靠。

当然,您仍然必须确保您的 C# 和 Delphi 代码都使用相同的或易于映射的枚举成员名称。

折衷方案可能是将值作为简单的字节数组传递 = 枚举的每个成员都有一个基础字节大小的序数值,因此只要 C# 中的枚举成员具有与枚举相同的基础序数值Delphi 中的成员,您可以根据需要简单地转换它们,例如,在您应该能够很容易地适应的非常粗糙的伪代码中:

给出:

     enumValues: array of Byte;
setVar: TSet; // set of TEnum

for i := 0 to Length(enumValues) do
Include(setVar, TEnum(enumValues[i]));

关于c# - 从 C# 将 Delphi 集传递给外部 Delphi 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1398873/

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