将记录作为函数结果从Delphi DLL传递给C ++ [英] Passing record as a function result from Delphi DLL to C++

查看:117
本文介绍了将记录作为函数结果从Delphi DLL传递给C ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我现在经历了一些很奇怪的事情。
当我将一个结构从C ++传递到一个Delphi DLL作为参数,一切正常。
但是,一旦我想要接收一个记录作为结果,我会得到错误的值或异常。
我停用记录的对齐方式,以便通过它们应该工作!

  





$ b < TSimpleRecord =打包记录
Nr1:Integer;
Nr2:Integer;
end;

// ...

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



我不知道为什么将此记录作为



感谢

/ p>

PS:正如我所说,C ++和Delphi都显示记录大小为8字节。

方案

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



你应该能够避免这个问题,明确使用<$

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

不要忘记相应更新C ++代码。



Rudy Velthuis撰写了这篇文章


这让我看到ABCVar结构体在寄存器EDX:EAX(EDX,顶部32位,EAX低级)返回。这不是德尔福所做的记录,甚至没有这种大小的记录。 Delphi将此类返回类型视为额外的var参数,并且不返回任何内容(因此函数实际上是一个过程)。



[...] b
$ b

Delphi作为EDX:EAX组合返回的唯一类型是Int64。


避免此问题的另一种方法是

  function TTest():Int64; cdecl; 
begin
TsimpleRecord(Result).Nr1:= 1;
TSimpleRecord(Result).Nr2:= 201;
end;请注意,即使在C ++中行为未定义的情况下,Delphi也允许这种类型的打印。 p>

I am experiencing some very strange things right now. When I am passing a struct from C++ to a Delphi DLL as a parameter everything works fine. However, as soon as I want to receive a record as a result I either get wrong values or exceptions. I deactivated the alignment of the record so that passing them should work! Heres the code!

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++ call :

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

I have got no idea why passing this record as a parameter works but not as a result of a function!?

Can anybody help me?`

Thanks

PS: As I said, both C++ and Delphi show that the record is 8 bytes large.

解决方案

Some compilers will return struct types (possibly depending on the size) in registers, others will add a hidden extra parameter where the result should be stored. Unfortunately, it looks like you're dealing two compilers that do not agree on how to return these.

You should be able to avoid the problem by explicitly using an out parameter instead.

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

Do not forget to update the C++ code accordingly.

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.

which suggests that an alternative way to avoid the problem is

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

Note that Delphi allows such type punning even in situations where the behaviour would be undefined in C++.

这篇关于将记录作为函数结果从Delphi DLL传递给C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆