On 07 Jun 2010, at 15:59, José Mejuto wrote:

Monday, June 7, 2010, 10:34:26 AM, you wrote:

JM> safecall is not supported (= ignored) on non-Windows platforms,
JM> because it is completely Windows-specific. Afaik, GCC does not support
JM> any safecall calling convention on Linux either.

It is "silently" changed by stdcall do not ?

It is completely ignored. So it is the same as the default calling convention (which is register on i386, and stdcall=register=cdecl=... on other platforms).

JM> Are you certain when using XPCOM with GCC, it automatically transforms
JM> every function so that

First I must conclude that XPCOM in Linux is compiled with GCC and
which version is being used, but I'm quite sure it is GCC ;)

JM> a) the result is passed as a hidden parameter by reference
JM> b) the actual function results becomes an error code

Plain function result is in EAX, if I call (in ASM) QueryInterface
with garbaged IIDs I get "$80004002" in the EAX (NOT_INTERFACE). Just
the same as in Windows using safecall except the stack clean.

Ok. In the mean time I found some more info about how XPCOM works:
* http://benjamin.smedbergs.us/blog/2008-09-26/allocated-memory-and-shared-library-boundaries/ : apparently, all code that makes use of XPCOM via C/C++ is supposed to be written in IDL, which is then transformed into C++ code that conforms to the safecall conventions (apart from the caller rather than the callee cleaning up). * https://developer.mozilla.org/En/Xptcall_Porting_Guide : a description of how the dispatching works (but that's not really relevant in case of FPC, since FPC natively supports calling COM interfaces on Linux).

JM> c) a check is inserted after every call that checks this error code

To check this I must compile something with GCC and I do not have it
installed and I do not have a source to compile with it. I should
investigate following other paths.

At first sight that does not happen in XPCOM, even on Windows (but since we do it on Windows, maybe we should also do it elsewhere for consistency reasons).

Could this be considered a bug in fpc interfaces ?

JM> Yes, it is always wrong to assume that "const" enforces passing by
JM> reference (except when using the mwpascal calling convention).

So a "const x: TGUID" will be passed by reference in safecall and as
16 bytes in cdecl ? Is this OK ? Is this how GCC excepts a const
parameter TGUID to be passed ?

In C, "const" does not modify how a parameter is passed in any way. If a parameter is passed by value without "const", then it's also passed by value with "const". The problems are a) in Pascal, the behaviour of const is completely undefined (the compiler can do whatever it wants) b) a lot of people use Pascal "const" as translation for C's "const *" for record parameters, which is wrong (but which sometimes works by accident)

Moreover, in FPC not all platforms consistently treat const record parameters the same as a regular parameters for cdecl (at least ARM currently always passes const records by reference for some reason). In short: "const" is a mess as far as predicting how it affects passing record parameters, and hence it should never be used in record parameter declarations for external C functions.

It's possible that it has a special meaning for safecall, I don't know.

I'm asking because now I have changed
my interface definition to use PGUID instead (both windows and linux)
and it works more or less, but now I have a problem in the
TInterfacedObject which seems to be the cause of some crashes, but I
can not say by now if it is related to XPCOM exposing a different
"IUnknown" (maybe cdecl instead stdcall) or TGUID related. I'll
investigate further.

I think that nobody who understands both on the code generator and the RTL side of COM interfaces ever worked on XPCOM interoperability on non-Windows.

One question, is there any way in fpc to "define" the calling
convention as a C define ? Just something like:

{$IFDEF UNIX}
 {$DEFINE THECALLING cdecl}
{$ELSE}
 {$DEFINE THECALLING safecall}
{$ENDIF}
function x: integer; THECALLING;

I had replaced all safecalls with:

{$IFDEF xx}safecall{$ENDIF}{$IFDEF y}cdecl{$ENDIF}

But it is quite "awful" :)

Yes, it is possible with {$macro on}. Example from the opengl unit:

{$MODE Delphi}
{$MACRO ON}
{$IFDEF Windows}
  {$DEFINE extdecl := stdcall}
{$ELSE}
  {$DEFINE extdecl := cdecl}
  {$IFDEF MorphOS}
    {$INLINE ON}
    {$DEFINE GL_UNIT}
  {$ELSE}
    {$LINKLIB c}
  {$ENDIF}
{$ENDIF}
...
var
  glAccum: procedure(op: GLenum; value: GLfloat); extdecl;


I'm personally not really interested in fixing this whole mess though. I spend a lot of time in the past disabling safecall in the compiler for all non-Windows platforms because it always generated wrong code elsewhere. Now it seems it should be
a) enabled everywhere, and then
b) fixed for all platforms, which requires modification to the parameter managers of most architectures (since most don't contain any support for safecall)


Jonas

_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply via email to