Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Passing Record (structure) data from DLL

434 views
Skip to first unread message

Gerald Johnson

unread,
Aug 4, 1999, 3:00:00 AM8/4/99
to
I would like to have a DLL stuff a record array with data and be able to
pass the entire record structure from the DLL to the calling program. Is
this possible and if so, what is the best approach.

Thanks for any help

Gerald

Nick Yevseyev

unread,
Aug 4, 1999, 3:00:00 AM8/4/99
to
Make sure that you have a record descriptions in all threads you sending the
record data. It means you have to add the description in DLL and in EXE, for
example.

Nick

Peter Below (TeamB)

unread,
Aug 5, 1999, 3:00:00 AM8/5/99
to
In article <7o9s1o$p1...@forums.borland.com>, Gerald Johnson wrote:
> I would like to have a DLL stuff a record array with data and be able to
> pass the entire record structure from the DLL to the calling program. Is
> this possible and if so, what is the best approach.
>

The best approach would be to have the EXE allocate the memory for the
array and pass the array as a Var parameter to the DLL for filling.
This way it is clear who owns the memory for the array and is responsible
for cleaning it up if required. The details depend on information you have
not given. E.g. do you know the size of the array at compile-time? Is the
DLL written in the same language as the executable? If not, which is the
Delphi side? What language is used for the other side?


Peter Below (TeamB) 10011...@compuserve.com)
No replies in private e-mail, please, unless explicitly requested!


Gerald Johnson

unread,
Aug 5, 1999, 3:00:00 AM8/5/99
to
Peter,

Thanks for the response.

What you suggested is actually what I am working on doing. The array
structure memory is allocated in the calling program (written using D3) and
passed to the DLL function (also written using D3).

The DLL function is declared as follows:

function RdTopupLog(Address : byte; var Topups : array of TTopupLog) :
word;
begin
.....
end;

In the main code, the array is declared as follows in the private section
of the object

TopupLog : Array[0..50] of TTopupLog;
feeder : byte;


and called as follows:

RdTopupLog(feeder, TopupLog);


Everything works fine when both functions are in the same project, but when
the DLL function is called while in the DLL, I get an access violation.

Am I doing something wrong?

Thanks

Gerald

Peter Below (TeamB) <10011...@compuXXserve.com> wrote in message ...

Gerald Johnson

unread,
Aug 5, 1999, 3:00:00 AM8/5/99
to
I resolved the problem.

As it turned out, I had a function name which duplicated some Windows API
function (ReadEventLog). It caused problems. Renaming the function
resolved the problem.

Thanks for the help.

Gerald


Sarah Lander

unread,
Aug 6, 1999, 3:00:00 AM8/6/99
to
This looks like something I might be able to use as well. My case involves a C++
DLL written by someone else. I've got to write the exe. Instead of passing
records, they'd therefore be passing the equivalent C/C++ structures. I can find
out the maximum possible size of the structures, but won't know how much of them
are actually being used when I compile.

Is this combination possible using the method you suggest? And how would I
allocate the memory?

Sarah

Peter Below (TeamB)

unread,
Aug 6, 1999, 3:00:00 AM8/6/99
to
> This looks like something I might be able to use as well. My case involves a C++
> DLL written by someone else. I've got to write the exe. Instead of passing
> records, they'd therefore be passing the equivalent C/C++ structures. I can find
> out the maximum possible size of the structures, but won't know how much of them
> are actually being used when I compile.
> Is this combination possible using the method you suggest? And how would I
> allocate the memory?


A C struct is basically the same as a Delphi record. You have to deal with
field alignment issues (need to know which #pragma align value the C compiler uses
by default, Delphi by default aligns fields in a record that has not been declared
with the packed keyword for optimal access, which depends on field size. See
Object Pascal Language Guide) and properly translate the field types used in C to
Delphi types (which means: no String fields! char fieldname[n] is fieldname: Array
[0..n-1] of Char in Delphi).

In C an array of structures parameter is usually declared in the form

structtype paramname[]

or

structtype* paramname

Both are in fact different notations for the same thing: a pointer to the array,
which is the same as a pointer to the arrays first element. So a possible
translation to Delphi, which avoids using pointers, is

Var paramname: TStructtype;

to which you then pass the *first* element of the array. Since this is a Var
parameter it results in passing the address of the first element, just what the C
side requires.

Since you do not know the number of array elements up front you have to allocate
memory for them at run-time, dynamically. Using a D4 dynamic array for this should
in principle work, e.g. you do a

Var
params: Array of TStructtype;
Begin
SetLength( params, numberofelementsneeded );
...init elements
DllFunction( params[0], numberofelementsneeded );

Note that the DLL function is handed the actual number of elements. If your DLL
interface does not allow for that it is probably seriously flawed, since the
DLLfunction has no way to determine how many entries the array you fed it has,
unless there is some convention to place a special marker record as last in the
array, for instance.

If you don't work with D4 you have to fall back to a pointer-to-array approach,
e.g.

Type
TStructArray = Array [0..High(Cardinal) div Sizeof( TStructtype )-1] of
TStructtype;
PStructArray = ^TStructArray;
Var
pParams: PStructArray;
Begin
pParams := AllocMem( numberofelementsneeded * Sizeof( TStructtype ));
try
...init pParams^[0] to pParams^[numberofelementsneeded-1]
DLLFunction( pParams^[0], numberofelementsneeded );
finally
FreeMem( pParams );
end;

0 new messages