另一个德尔福互操作问题......
我有这个Delphi代码:
library DelphiDll;
uses
Dialogs,
SysUtils,
Classes;
type
TestEnum = (teOne, teTwo);
TTestRecord = record
end;
TTestType = record
MyTestRecords: array [1..255] of TTestRecord;
MyTestEnum: TestEnum;
end;
{$R *.res}
function DllFunction(var testType: TTestType): Boolean stdcall; export;
begin
testType.MyTestEnum := teTwo;
Result := True;
end;
exports DllFunction;
begin
end.
这个C#代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace DelpiDllTester
{
public enum TestEnum
{
One,
Two
}
[StructLayout(LayoutKind.Sequential)]
public struct TestType
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 255)]
public TestRecord[] MyTestRecords;
public TestEnum MyTestEnum;
}
[StructLayout(LayoutKind.Sequential)]
public struct TestRecord
{
}
class Program
{
[DllImport("DelphiDll.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
public static extern bool DllFunction(ref TestType testType);
static void Main(string[] args)
{
TestType testType = new TestType();
bool dllFunctionResult = DllFunction(ref testType);
Console.WriteLine(dllFunctionResult);
Console.WriteLine(testType.MyTestEnum);
Console.ReadLine();
}
}
}
当我运行C#代码时,testType.MyTestEnum的控制台输出始终是枚举值,即使它在Delphi代码中显然设置为2。
现在,如果我只是将TestType结构中的TestRecord结构数组改为使用简单的整数数组,那么一切都很好。
为什么整数数组不起作用,结构数组却没有?
答案 0 :(得分:3)
主要问题是TTestRecord
没有定义内容。 C#代码将其作为大小为1的字段进行编组.Delphi编译器将其视为大小为0.因此两个结构之间存在不匹配。 C#代码为Marshal.SizeOf(typeof(TestType))
返回260,而Delphi编译器为SizeOf(TTestType)
返回8。
在真实代码中,可能会在该记录中有一些实际内容,当你这样做时,一切都将开始起作用。
请注意,@ JMarsch和@Ken White也会生成有效积分。您需要确保正确编组枚举并且struct
布局匹配。由于结构的填充方式,你可能会在没有对你的枚举编组做任何事情的情况下离开,但你可能同样不幸运!
答案 1 :(得分:2)
自从我使用Delphi(如'98)以来,这已经是整整一生了,但是,我记得,Delphi中的枚举是1个字节的数字。 c#中的枚举是整数(32位)。
因此,您可以尝试将c#enum定义为
enum TestEnum: byte {One, Two}
这个问题没有解释它是如何使用int数组的。关于我能想到的唯一另一件事就是确保c#enum的值与Delphi Enum的值完全匹配(所以使用teOne,teTwo),但由于我们实际上是在谈论一个整数/字节,我不明白这有多重要。
答案 2 :(得分:2)
您需要在Delphi代码中设置枚举大小。 Delphi将尽可能小,但.NET方需要int
。在枚举声明之前将以下内容添加到代码中:
{$MINENUMSIZE 4} // can also use {$Z4} but it's not clear later when
// you're trying to maintain the code.
// Or you can use {$Z-} and {$Z+}, for
// {$Z1} and {$Z4} respectively
// Your enum declaration
{$MINENUMSIZE 1}