我现在正在经历一些非常奇怪的事情。
当我将结构从 C++ 传递到 Delphi DLL 作为参数时,一切正常。
但是,一旦我想收到结果记录,我要么得到错误的值,要么得到异常。
我禁用了记录的对齐,以便通过它们应该可以!
这是代码!
德尔福动态链接库:
TSimpleRecord = packed record
Nr1 : Integer;
Nr2 : Integer;
end;
//...
function TTest() : TSimpleRecord; cdecl;
begin
Result.Nr1 := 1;
Result.Nr2 := 201;
ShowMessage(IntToStr(SizeOf(Result)));
end;
C++ 调用:
#pragma pack(1)
struct TSimpleRecord
{
int Nr1;
int Nr2;
};
//...
typedef TSimpleRecord (__cdecl TestFunc)(void);
TestFunc* Function;
HINSTANCE hInstLibrary = LoadLibrary("Reactions.dll");
if (hInstLibrary)
{
Function = (TestFunc*)GetProcAddress(hInstLibrary, "TTest");
if (Function)
{
TSimpleRecord Result = {0};
Result = Function();
printf("%d - %d - %d", sizeof(Result), Result.Nr1, Result.Nr2);
cin.get();
}
}
我不知道为什么将此记录作为参数传递有效,但不能作为函数的结果传递!?
有人能帮我吗?
Thanks
PS:正如我所说,C++和Delphi都显示记录是8字节大。
有些编译器会返回struct
类型(可能取决于大小)在寄存器中,其他人会添加一个隐藏的额外参数来存储结果。不幸的是,看起来您正在处理两个编译器,它们在如何返回这些内容上没有达成一致。
您应该能够通过显式使用来避免该问题out
参数代替。
procedure TTest(out Result: TSimpleRecord); cdecl;
begin
Result.Nr1 := 1;
Result.Nr2 := 201;
end;
不要忘记相应地更新 C++ 代码。
鲁迪·维尔修斯 (Rudy Velthuis) 写过相关文章 http://rvelthuis.de/articles/articles-convert.html:
这向我展示了 ABCVar 结构体在寄存器 EDX:EAX 中返回(EDX 具有最高 32 位,EAX 具有较低位)。这根本不是 Delphi 处理记录的方式,即使处理这种大小的记录也是如此。 Delphi 将此类返回类型视为额外的 var 参数,并且不返回任何内容(因此该函数实际上是一个过程)。
[...]
Delphi 以 EDX:EAX 组合形式返回的唯一类型是 Int64。
这表明避免该问题的另一种方法是
function TTest() : Int64; cdecl;
begin
TSimpleRecord(Result).Nr1 := 1;
TSimpleRecord(Result).Nr2 := 201;
end;
请注意,即使在 C++ 中未定义行为的情况下,Delphi 也允许此类类型双关。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)