Passing record as a function result from Delphi DLL to C++
c++, delphi, dll
Solution
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++.
Problem
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.