Hello FPC-Pascal, Monday, June 7, 2010, 4:25:59 PM, you wrote:
>> It is "silently" changed by stdcall do not ? JM> It is completely ignored. So it is the same as the default calling JM> convention (which is register on i386, and stdcall=register=cdecl=... JM> on other platforms). Wow, that looks "dangerous" at least it should produce a warning when used in interfaces, or as safecall is a form of stdcall (with return values check) replace by stdcall. >> 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. The functions declared in the interfaces now with "cdecl" crashes the program as the stack remains unbalanced after call due extra 4 bytes in it, which i think it is the "hidden parameter result". JM> Ok. In the mean time I found some more info about how XPCOM works: JM> http://benjamin.smedbergs.us/blog/2008-09-26/allocated-memory-and-shared-library-boundaries/ JM> : apparently, all code that makes use of XPCOM via C/C++ is supposed JM> to be written in IDL, which is then transformed into C++ code that JM> conforms to the safecall conventions (apart from the caller rather JM> than the callee cleaning up). Yes, that's the "whole picture". >> 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. JM> At first sight that does not happen in XPCOM, even on Windows (but JM> since we do it on Windows, maybe we should also do it elsewhere for JM> consistency reasons). Maybe, but that's not a great problem, maybe do it only in the case of "Verify method calls" ? JM> In C, "const" does not modify how a parameter is passed in any way. If JM> a parameter is passed by value without "const", then it's also passed JM> by value with "const". The problems are JM> a) in Pascal, the behaviour of const is completely undefined (the JM> compiler can do whatever it wants) JM> b) a lot of people use Pascal "const" as translation for C's "const *" JM> for record parameters, which is wrong (but which sometimes works by JM> accident) Yes, but removing the "const" still passes the parameter as 16 bytes, and defining it as "var" creates problems when passing an interface to extract the GUID instead passing the interface reference. Anyway most of this problems are quite easy to be bypassed with some source changes which still remain compatible between windows and linux. The great problem now is the extra parameter in the stack which imposes me to wrap all interfaces in some kind of assembler functions to compensate the stack. JM> Moreover, in FPC not all platforms consistently treat const record JM> parameters the same as a regular parameters for cdecl (at least ARM JM> currently always passes const records by reference for some reason). JM> In short: "const" is a mess as far as predicting how it affects JM> passing record parameters, and hence it should never be used in record JM> parameter declarations for external C functions. I understand, but now the question is which one to use instead ? const passes 16 bytes, var does not allow to pass a constant and no definition passes also 16 bytes. Maybe use a formal parameter ? >> 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. JM> I think that nobody who understands both on the code generator and the JM> RTL side of COM interfaces ever worked on XPCOM interoperability on JM> non-Windows. This has been solved the "QueryReferent" function must be stdcall and pass TGUID because it is being called by fpc. >> One question, is there any way in fpc to "define" the calling >> convention as a C define ? Just something like: JM> Yes, it is possible with {$macro on}. Example from the opengl unit: JM> {$MODE Delphi} JM> {$MACRO ON} JM> {$IFDEF Windows} JM> {$DEFINE extdecl := stdcall} JM> {$ELSE} JM> {$DEFINE extdecl := cdecl} JM> {$IFDEF MorphOS} JM> {$INLINE ON} JM> {$DEFINE GL_UNIT} JM> {$ELSE} JM> {$LINKLIB c} JM> {$ENDIF} JM> {$ENDIF} JM> ... JM> var JM> glAccum: procedure(op: GLenum; value: GLfloat); extdecl; Ok, I'll use it. I hate macros, but this time they seems quite useful. JM> I'm personally not really interested in fixing this whole mess though. JM> I spend a lot of time in the past disabling safecall in the compiler JM> for all non-Windows platforms because it always generated wrong code JM> elsewhere. Now it seems it should be JM> a) enabled everywhere, and then JM> b) fixed for all platforms, which requires modification to the JM> parameter managers of most architectures (since most don't contain any JM> support for safecall) That looks as a hard job :( I can only help testing XPCOM in both windows and linux, but I doubt that I can help in the compiler side :( Maybe it is possible in some way to define some kind of plugable calling convention generator ? Just like a script to define the calling convention when it is not any of the standard ? Thinking again, it does not look like a great idea :( Now I must think in how to solve the extra integer in the stack when calling functions :( -- Best regards, José _______________________________________________ fpc-pascal maillist - fpc-pascal@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-pascal