Board index » cppbuilder » Returning a Delphi interface from a C++ class implementing it

Returning a Delphi interface from a C++ class implementing it


2006-08-10 04:30:23 AM
cppbuilder48
Hi all,
Once again, I know this forum is not for technical questions, but I
could not find one that matches the area I'm looking at. If you figure
out a best place, please tell me.
Anyway, here is my new problem:
I'm getting an access violation (access to 000000) in this code:
static _di_INewService __fastcall Create()
{
_di_INewService result;
TNewService_Proxy* proxy = new TNewService_Proxy();
if (proxy->QueryInterface(INewService_IID, result))
return result;
};
The AV occurs on the call to QueryInterface. I don't understand why this
happens and sincerely hope someone can help. You will find the
declarations for _di_INewService and TNewService_Proxy at the end of
this message and were inspired by what dcc32 does when generating the
hpp file from a pascal file. Note that the interface and class MUST be
compatible with the delphi ones because they will be passed to functions
in delphi units.
Once again, many thanks for any help.
Olivier Sannier
__interface INewService;
typedef System::DelphiInterface<INewService>_di_INewService;
__interface INTERFACE_UUID("{3D581A93-D126-49DB-82BA-5EF7818657BC}")
INewService : public IInterface
{
public:
virtual int __fastcall Sum(
const int A,
const int B
) = 0; // pure virtual function - interface only
virtual TDateTime __fastcall GetServerTime(
) = 0; // pure virtual function - interface only
};
class DELPHICLASS TNewService_Proxy;
class TNewService_Proxy : public TROProxy
{
typedef TROProxy inherited;
protected:
virtual AnsiString __fastcall __GetInterfaceName()
{ return "NewService"; }
virtual int __fastcall Sum(
const int A,
const int B
);
virtual TDateTime __fastcall GetServerTime(
);
public:
#pragma option push -w-inl
/* TROProxy.Create */ inline __fastcall virtual TNewService_Proxy(const
Uroclientintf::_di_IROMessage aMessage, const
Uroclientintf::_di_IROTransportChannel aTransportChannel)/* overload */ :
TROProxy(aMessage, aTransportChannel) {}
#pragma option pop
public:
#pragma option push -w-inl
/* TObject.Destroy */ inline __fastcall virtual ~TNewService_Proxy() {}
#pragma option pop
private:
void *__INewService; /* NewLibrary_Intf_intf::INewService */
public:
operator INewService*() { return (INewService*)&__INewService; }
};
 
 

Re:Returning a Delphi interface from a C++ class implementing it

"OBones" < XXXX@XXXXX.COM >wrote in message
Quote
TNewService_Proxy* proxy = new TNewService_Proxy();
That is a memory leak if QueryInterface() fails. It is also a memory leak
if the reference count for the object begins at 1 instead of 0. You did not
show how TNewService_Proxy is actually implemented.
Quote
if (proxy->QueryInterface(INewService_IID, result))
You need to use the '&' operator:
if (proxy->QueryInterface(IID_INewService, (LPVOID*)&result))
Quote
The AV occurs on the call to QueryInterface.
You are passing a NULL pointer to QueryInterface(). In fact, the code
shouldn't even compile since QueryInterface() expects a void** instead of a
void*.
Quote
Note that the interface and class MUST be compatible with the delphi
ones because they will be passed to functions in delphi units.
Then you should be implementing the object in Pascal to begin with. The C++
interface declarations you see are generated from Pascal interfaces anyway.
Gambit
 

Re:Returning a Delphi interface from a C++ class implementing it

Remy Lebeau (TeamB) wrote:
Quote
"OBones" < XXXX@XXXXX.COM >wrote in message
news:44da45dc$ XXXX@XXXXX.COM ...

>TNewService_Proxy* proxy = new TNewService_Proxy();

That is a memory leak if QueryInterface() fails. It is also a memory leak
if the reference count for the object begins at 1 instead of 0.
yes, I understand the first leak, but how could a reference count start
at 1 when I just created the instance? Is TInterfacedObject doing weird
things that I'm not aware of?
Quote
You did not show how TNewService_Proxy is actually implemented.
The declaration I showed should be self sufficient, as most methods are
inline. The only that are not are simply returning A+B and the current time.
Quote
>The AV occurs on the call to QueryInterface.

You are passing a NULL pointer to QueryInterface(). In fact, the code
shouldn't even compile since QueryInterface() expects a void** instead of a
void*.
Well, no, it's not, as ultimately the TNewService_Proxy class derives
from TInterfacedObject.
Quote
>Note that the interface and class MUST be compatible with the delphi
>ones because they will be passed to functions in delphi units.

Then you should be implementing the object in Pascal to begin with. The C++
interface declarations you see are generated from Pascal interfaces anyway.
Nope they are not, as I said, they are "inspired from" what gets
generated. And having a pascal source file is NOT an option and will
most likely never will be.
And I actually replaced the three lines showed initially with this:
return new TNewService_Proxy(aMessage, aTransportChannel)->
operator INewService*();
which compiles just as well, but crashes as well too.
Actually, I expected it to crash as the private member void
*__INewService inside INewService is never initialized. I understand
it's the delphi code doing it under the hood, I just have to figure out
a way to do it myself then.
 

{smallsort}