In extension to this question, I guess I'll best show what I've got so far. What I'm trying to do is create a Firefox extension with Delphi, that'll work with the Firefox versions of the future that will use an exported NSModule structure, and no longer an NSGetModule function.
Main questions I'm struggling with for the moment is:
@mozilla.org/network/protocol;1?name=xxm
contract)The code I'm trying to port is here: http://mxr.mozilla.org/mozilla-central/source/xpcom/components/Module.h
type
TConstructorProcPtr=function(aOuter:nsISupports;const aIID:TGUID;var aResult:pointer):nsresult;
TLoadFuncPrt=function:nsresult;
TUnloadFuncPrt=procedure;
TCIDEntry=record
cid:TGUID;
service:boolean;
getFactoryProc:pointer;//TGetFactoryProcPtr;
constructorProc:TConstructorProcPtr;
end;
TContractIDEntry=record
contractid:PChar;
cid:TGUID;//PGUID?
end;
TCategoryEntry=record
category,entry,value:PChar;
end;
TXPCOMModule=packed record
kVersion:integer;//=1;
mVersion:cardinal;//kModuleVersion
mCIDs:^TCIDEntry;//pointer to first in array, last should be nil
mContractIDs:^TContractIDEntry;//pointer to first in array, last should be nil
mCategoryEntries:^TCategoryEntry;//pointer to first in array, last should be nil
getFactoryProcPtr:pointer;//TGetFactoryProcPtr;
loadProc:TLoadFuncPrt;
unloadProd:TUnloadFuncPrt;
end;
You almost certainly need the cdecl
calling convention on all your procedure- and function-pointer declarations:
TConstructorProcPtr = function(aOuter: nsISupports; const aIID: TGUID; var aResult: Pointer): nsresult; cdecl;
TLoadFuncPrt = function: nsresult; cdecl;
TUnloadFuncPrt = procedure; cdecl;
I assume you've declared nsISupports
as a Delphi interface. Otherwise, you need to make sure the aOuter
parameter above is a pointer as it is in the C++ code.
For TContractIDEntry
, and all the other places where you use PChar
, I advise you to use PAnsiChar
instead. The size of Delphi's Char
type changed a couple of years ago, but the C++ char
is and always will be one byte, so use Delphi's one-byte character type explicitly. Also, your comment wondering whether to declare the cid
field as a PGUID
was correct; asterisk means pointer.
TContractIDEntry = record
contractid: PAnsiChar;
cid: PGUID;
end;
The kVersion
field should not be a member of the record you declare. In C++, it's a static member, which means it occupies no space in the structure itself; it's shared by all instances of that type. It's equivalent to a class field in a Delphi class, but I don't think records offer that feature. Make it a unit-level variable instead of a field.