我现在正在经历一些非常奇怪的事情.当我将结构从C++传递给Delphi DLL作为参数时,一切正常.但是,一旦我想收到一条记录,我就会得到错误的值或异常.我停用了记录的对齐方式,以便传递它们!继承人的代码!
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;
Run Code Online (Sandbox Code Playgroud)
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();
}
}
Run Code Online (Sandbox Code Playgroud)
我不知道为什么将这条记录作为参数传递但不是函数的结果!?
有人能帮助我吗?`
谢谢
PS:正如我所说,C++和Delphi都显示该记录大8字节.
小智 5
一些编译器将返回struct寄存器中的类型(可能取决于大小),其他编译器将添加隐藏的额外参数,其中应存储结果.不幸的是,看起来你正在处理两个不同意如何返回这些的编译器.
您应该能够通过显式使用out参数来避免此问题.
procedure TTest(out Result: TSimpleRecord); cdecl;
begin
Result.Nr1 := 1;
Result.Nr2 := 201;
end;
Run Code Online (Sandbox Code Playgroud)
不要忘记相应地更新C++代码.
这向我展示了ABCVar结构在寄存器EDX:EAX(具有前32位的EDX和具有较低位的EAX)中返回.这不是Delphi所做的记录,甚至不是这个尺寸的记录.Delphi将这些返回类型视为额外的var参数,并且不返回任何内容(因此该函数实际上是一个过程).
[...]
Delphi作为EDX返回的唯一类型:EAX组合是Int64.
这表明避免这个问题的另一种方法是
function TTest() : Int64; cdecl;
begin
TSimpleRecord(Result).Nr1 := 1;
TSimpleRecord(Result).Nr2 := 201;
end;
Run Code Online (Sandbox Code Playgroud)
请注意,即使在C++中未定义行为的情况下,Delphi也允许这种类型惩罚.
| 归档时间: |
|
| 查看次数: |
2323 次 |
| 最近记录: |