Am 30.06.2012 12:50 schrieb Bernd prof7...@gmail.com:
2012/6/30 Sven Barth pascaldra...@googlemail.com:
Your explanation is very nice and mostly correct, but in case of
external
cdecl functions in FPC the varargs modifier and a array of const
parameter imply the same C compatible parameter passing in the
compiler. See
also here:
http://freepascal.org/docs-html/ref/refsu77.html#x180-1914.9.17
The only difference is when calling the functions. E.g.:
procedure a(args: array of const); cdecl; external;
procedure b; cdecl; varargs; external;
begin
a([1, 'foo', somevar]);
b(1, 'foo', somevar);
end.
This means in my case I declared the external function correctly and
only need to pass
[nil]
to make it a null terminated list? Because I tried this last night and
looked at the generated assembler and if I for example call it with
purple_prpl_got_user_status(@self, Pointer(AName),
Pointer(AStatusID), [1,2,3,nil]);
then it will generate the following code:
0162EF17 6a00 push $0x0
0162EF19 6a03 push $0x3
0162EF1B 6a02 push $0x2
0162EF1D 6a01 push $0x1
0162EF1F ff75f8 pushl -0x8(%ebp)
0162EF22 ff75fc pushl -0x4(%ebp)
0162EF25 8b45f4 mov-0xc(%ebp),%eax
0162EF28 50 push %eax
0162EF29 e8b20afaff call 0x15cf9e0
purple_prpl_got_user_status@plt
so its just just pushing the contents of the list onto the stack as
they are and If I pass [] there would be nothing pushed at all, so the
right thing for me to do in this case would be to call it with
purple_prpl_got_user_status(@self, Pointer(AName), Pointer(AStatusID),
[nil]);
0162EF17 6a00 push $0x0
0162EF19 ff75f8 pushl -0x8(%ebp)
0162EF1C ff75fc pushl -0x4(%ebp)
0162EF1F 8b45f4 mov-0xc(%ebp),%eax
0162EF22 50 push %eax
0162EF23 e8b80afaff call 0x15cf9e0
purple_prpl_got_user_status@plt
so that it will push exactly one zero onto the stack, so it gets what
it wants (an empty null-terminated list)? Then my only mistake was to
assume that [] would automatically generate a null terminated list
(for automagic[TM] C-friendlyness) just like strings do?
I have now looked at your mail again. Normally you don't need to explicitly
pass a Nil (whatever of the earlier mentioned variants you chose) as e.g.
for printf the following works:
printf(%d %d %d, 1, 2, 3);
or
printf(%d %d %d, [1, 2, 3]);
(depending on the declaration)
But the comment above the original C function you mentioned in your initial
mail explicitly states that you must pass a Null-terminated list, which the
compiler doesn't do by itself. Maybe that is told to GCC by the
G_GNUC_NULL_TERMINATED define (whatever it resolves to...)
Nevertheless passing a Nil at the end should be the correct approach in
your specific case.
Regards,
Sven
___
fpc-pascal maillist - fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal