I'm having trouble converting a class from a C header to use in Delphi.
A snippet of the declaration in the C header file looks like this:
class __declspec(uuid("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"))
ISomeInterface
{
public:
virtual
BOOL
SomeBoolMethod(
VOID
) const = 0;
}
I'm writing a DLL which exports a method that accepts a ISomeInterface parameter, e.g.
function MyExportFunc (pSomeInterface: ISomeInterface): Cardinal; export; stdcall;
var
aBool: BOOL;
begin
aBool := pSomeInterface.SomeBoolMethod;
end;
I've declared ISomeInterface in Delphi like this:
type ISomeInterface = class
function SomeBoolMethod: BOOL; cdecl; virtual; abstract;
end;
Calling the pSomeInterface.SomeBoolMethod results in an access violation.
Am I doing something fundamentally wrong?
The actual C header is httpserv.h and I'm trying to implement an IIS7 native module in Delphi.
Some c++ code which works looks like this:
HRESULT
__stdcall
RegisterModule(
DWORD dwServerVersion,
IHttpModuleRegistrationInfo * pModuleInfo,
IHttpServer * pHttpServer
)
{
// etc
}
When debugging I see that the pModuleInfo parameter contains a __vfptr member which has 6 members under it (named [0] to [5] and have addresses as the values) which I deduce are pointers the virtual methods in the IHttpModuleRegistrationInfo class.
The Delphi RegisterModule export now looks like this:
function RegisterModule (dwServerVersion: DWORD; var pModuleInfo: Pointer; var pHttpServer: Pointer): HRESULT; export; stdcall;
begin
// etc
end;
pModuleInfo contains the equivalent address to the __vfptr member in the cpp example, and assuming the order in __vfptr is the same as the class declaration in the header file I extract the method addresses:
function RegisterModule (dwServerVersion: DWORD; var pModuleInfo: Pointer; var pHttpServer: Pointer): HRESULT; export; stdcall;
var
vfptr: Pointer;
ptrGetName: Pointer;
ptrGetId: Pointer;
begin
vfptr := pModuleInfo;
ptrGetName := Pointer (Pointer (Cardinal(vfptr))^);
ptrGetId := Pointer (Pointer (Cardinal(vfptr) + 4)^);
end;
I now have the method address to call, so now I just need to invoke it somehow. I am probably going about this all the wrong way though!
__declspec(uuid
attached an UUID to class definition so that compiler could apply it somewhere else in code when it is requested by__uuidof
operator.That is, if you are porting to Delphi, you might be able basically omit this specification from the class. As for interfaces, when you declare an interface with Delphi you definitely have a chance to provide an IID to this definition.
Access Violation in your code is however not quite related to __declspec. Your C++
ISomeInterface
is not exactly an interface as it is not inherited fromIUnknown
. IIRC, with Delphi you just cannot declare an interface of this kind, whatever you declare has to be derived from at leastIUnknown
. So there is no way to safely and easily convert the interface (to be exact, the class - as it is not a valid COM interface definition).Here is the match/conversion done correctly:
And its Delphi twin from http://code.google.com/p/dspack/source/browse/trunk/src/DirectX9/DirectSound.pas#456