加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

将记录作为Delphi DLL到C的函数结果传递

发布时间:2020-12-15 04:20:50 所属栏目:大数据 来源:网络整理
导读:我现在正在经历一些非常奇怪的事情. 当我将结构从C传递给Delphi DLL作为参数时,一切正常. 但是,一旦我想收到一条记录,我就会得到错误的值或异常. 我停用了记录的对齐方式,这样传递它们就可以了! 继承人的代码! Delphi DLL: TSimpleRecord = packed record
我现在正在经历一些非常奇怪的事情.
当我将结构从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;

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();
        }
    }

我不知道为什么将此记录作为参数传递但不是作为函数的结果!?

有人能帮帮我吗?

谢谢

PS:正如我所说,C和Delphi都表明该记录大8字节.

解决方法

一些编译器将在寄存器中返回结构类型(可能取决于大小),其他编译器将添加一个隐藏的额外参数,其中应存储结果.不幸的是,看起来你正在处理两个不同意如何返回它们的编译器.

您应该能够通过显式使用out参数来避免此问题.

procedure TTest(out Result: TSimpleRecord); cdecl;
begin
  Result.Nr1 := 1;
  Result.Nr2 := 201;
end;

不要忘记相应地更新C代码.

Rudy Velthuis has written about this:

This showed me that the ABCVar struct was returned in the registers EDX:EAX (EDX with the top 32 bits,and EAX with the lower ones). This is not what Delphi does with records at all,not even with records of this size. Delphi treats such return types as extra var parameters,and does not return anything (so the function is actually a procedure).

[…]

The only type which Delphi returns as EDX:EAX combination is Int64.

这表明避免这个问题的另一种方法是

function TTest() : Int64; cdecl;
begin
  TSimpleRecord(Result).Nr1 := 1;
  TSimpleRecord(Result).Nr2 := 201;
end;

请注意,即使在C中未定义行为的情况下,Delphi也允许这种类型惩罚.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读