www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - D ABI and C++ COM-like interface

reply Pierre Renaux <Pierre_member pathlink.com> writes:
Hi,

I got a quite extensive code base written in C++ (~1.5Mil lines of code), so
porting all of that to D is not an option.

However all the code use a consistent object model that looks somewhat like COM.
So a C++ interface is defined for ALL objects and modules that can be
implemented. There's an introspection API that allows to list all methods,
properties, interfaces, and objects defined in each modules. This allows for
easy integration with other languages, including writting modules in other
languages.

So far there's a complete interop layer for the .NET platform, and for a
LUA-like language called squirrel. Both these can access 100% of the API written
in C++ and also implement interfaces.

Considering that D has access to low level assembly, I would think that it would
be easy to write a small library that contains the few low-level entry points of
the object model. That is :
iUnknown* CreateInstance(ObjectType)
bool ImportModule(Name,Flags,...)

That's all that is needed.

Now the "tricky" part is to make sure that I can redefine the interfaces in D
and make sure that their VTable and ABI is the same as a C++ VTable.

If it's already the case, then it should be a piece of cake. The only thing
would be to write a D interface :
// In D
interface iUnknown {
int AddRef();
int Release();
}

Now the methods of the interfaces all use __stdcall as calling convention,
although it could be changed if it's necessary.

Worst case I can write a function "CallMethod" in D and then generate a wrapper
class for each interface that would use that method (there is one in C++ that is
used by the Squirrel interop). Now that would be quite a bit slower than calling
the C++ interface directly obviously.

So the question is, does anybody knows if the ABI for the vtable and calling
convention for those methods are the same as C++ stdcall, and if not, is at
least the vtable at the same position (if not it could be possible to add a
dummy method to offset the vtable), and if the calling convention is __stdcall,
if not I can change the calling convention but I need to know what D uses...

Also, considering that the object model is fixed, and there isnt two ways of
calling the methods of those interfaces, I was thinking that I could aswell take
the GDC compiler and add an extension to the D language that would make sure
that those C++ interfaces can be called easily. That would allow a good level of
interop for any C++ library aswell as for my particular object model.


Best Regards,
- Pierre
Dec 27 2005
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"Pierre Renaux" <Pierre_member pathlink.com> wrote in message 
news:dot1fr$1o1t$1 digitaldaemon.com...
 Now the "tricky" part is to make sure that I can redefine the interfaces 
 in D
 and make sure that their VTable and ABI is the same as a C++ VTable.
No problem. Inherit from IUnknown (in windows.iunknown) and you're there. You don't have to use the windows.iunknown one, any interface you define called IUnknown will have the same effect.
 If it's already the case, then it should be a piece of cake. The only 
 thing
 would be to write a D interface :
 // In D
 interface iUnknown {
 int AddRef();
 int Release();
 }

 Now the methods of the interfaces all use __stdcall as calling convention,
 although it could be changed if it's necessary.
Using extern (Windows) will give a function __stdcall linkage. But any class that derives from IUknown will have __stdcall linkage by default.
Dec 27 2005
next sibling parent reply "Chris Miller" <chris dprogramming.com> writes:
On Tue, 27 Dec 2005 23:08:39 -0500, Walter Bright  
<newshound digitalmars.com> wrote:

 "Pierre Renaux" <Pierre_member pathlink.com> wrote in message
 news:dot1fr$1o1t$1 digitaldaemon.com...
 Now the "tricky" part is to make sure that I can redefine the interfaces
 in D
 and make sure that their VTable and ABI is the same as a C++ VTable.
No problem. Inherit from IUnknown (in windows.iunknown) and you're there. You don't have to use the windows.iunknown one, any interface you define called IUnknown will have the same effect.
It's the name IUnknown that makes the interface work with COM? I thought it was the extern(Windows) on it that did that. hmmm ...
 If it's already the case, then it should be a piece of cake. The only
 thing
 would be to write a D interface :
 // In D
 interface iUnknown {
 int AddRef();
 int Release();
 }

 Now the methods of the interfaces all use __stdcall as calling  
 convention,
 although it could be changed if it's necessary.
Using extern (Windows) will give a function __stdcall linkage. But any class that derives from IUknown will have __stdcall linkage by default.
Too many special cases :(
Dec 27 2005
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"Chris Miller" <chris dprogramming.com> wrote in message 
news:op.s2g8y6awpo9bzi moe...
 On Tue, 27 Dec 2005 23:08:39 -0500, Walter Bright 
 <newshound digitalmars.com> wrote:

 "Pierre Renaux" <Pierre_member pathlink.com> wrote in message
 news:dot1fr$1o1t$1 digitaldaemon.com...
 Now the "tricky" part is to make sure that I can redefine the interfaces
 in D
 and make sure that their VTable and ABI is the same as a C++ VTable.
No problem. Inherit from IUnknown (in windows.iunknown) and you're there. You don't have to use the windows.iunknown one, any interface you define called IUnknown will have the same effect.
It's the name IUnknown that makes the interface work with COM?
Yes.
Dec 27 2005
parent reply Thomas Kuehne <thomas-dloop kuehne.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Walter Bright schrieb am 2005-12-28:
 "Chris Miller" <chris dprogramming.com> wrote in message 
 news:op.s2g8y6awpo9bzi moe...
 On Tue, 27 Dec 2005 23:08:39 -0500, Walter Bright 
 <newshound digitalmars.com> wrote:

 "Pierre Renaux" <Pierre_member pathlink.com> wrote in message
 news:dot1fr$1o1t$1 digitaldaemon.com...
 Now the "tricky" part is to make sure that I can redefine the interfaces
 in D
 and make sure that their VTable and ABI is the same as a C++ VTable.
No problem. Inherit from IUnknown (in windows.iunknown) and you're there. You don't have to use the windows.iunknown one, any interface you define called IUnknown will have the same effect.
It's the name IUnknown that makes the interface work with COM?
Yes.
Where is this documented? http://www.digitalmars.com/d/class.html (no comments) http://www.digitalmars.com/d/interface.html (talks only about std.c.windows.com.IUnknown and not std.windows.iunknown.IUnknown) Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFDspSO3w+/yD4P9tIRAsLfAJwOpuGl7ePUjwmUCtkXiotdJvYmfACgxRU+ TU96A05+Vnf/uYc3BWDK7eo= =XmE9 -----END PGP SIGNATURE-----
Dec 28 2005
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"Thomas Kuehne" <thomas-dloop kuehne.cn> wrote in message 
news:etga83-pci.ln1 birke.kuehne.cn...
 It's the name IUnknown that makes the interface work with COM?
Yes.
Where is this documented? http://www.digitalmars.com/d/class.html (no comments) http://www.digitalmars.com/d/interface.html (talks only about std.c.windows.com.IUnknown and not std.windows.iunknown.IUnknown)
It isn't. Looks like I have work to do.
Dec 28 2005
parent Derek Parnell <derek psych.ward> writes:
An example of The Understatement ...


On Wed, 28 Dec 2005 16:40:43 -0800, Walter Bright wrote:
 Looks like I have work to do.
-- Derek (skype: derek.j.parnell) Melbourne, Australia "A learning experience is one of those things that says, 'You know that thing you just did? Don't do that.'" - D.N. Adams 29/12/2005 1:27:49 PM
Dec 28 2005
prev sibling next sibling parent Pierre Renaux <Pierre_member pathlink.com> writes:
Hi,

Thanks, that sounds good, I looked in the GDC and DMD sources about that and
there's a 'com' flag that define if an interface is COM-like or not. It sets it
as being COM-like if on of the base interfaces is called IUnknown, which is fair
enought, although it's a bit dirty...

That makes the methods being called with LINKwindows (I guess that's the
__stdcall convention) and removes the offset at the begining of the vtable.

Wouldnt it be better to be able to have a flage like extern(C) or define the
interface with a special keyword ? That would be cleaner, and most importantly
allow to define other interfaces than IUnknown has being COM-like.

Most of the API relies on iUnknown as base (not IUnknown - lower case 'i'), it's
'ok' to call it IUnknown in D. But, I also have other interfaces that are base
interfaces, mainly iSerializable and iDispatch that dont derive from iUnknown.
There's only a handfull of those, I could just make them inherit from iUnknown.
But well, it would still be slicker if I could just have something like :
interface(COM) iStuff {
}

that would be much cleaner.

Anyway thanks for the fast reply, is there any place where a 'feature' like this
could be requested ?

Can I implement it myself in the DMD base ? Mainly I'm concerned about how to
get it submitted and integrated (as in make it in GDC... or ? there's no source
code for the 'standard' D compiler), doing it isnt really the issue.


- Pierre




In article <dot4aq$1pgm$1 digitaldaemon.com>, Walter Bright says...
"Pierre Renaux" <Pierre_member pathlink.com> wrote in message 
news:dot1fr$1o1t$1 digitaldaemon.com...
 Now the "tricky" part is to make sure that I can redefine the interfaces 
 in D
 and make sure that their VTable and ABI is the same as a C++ VTable.
No problem. Inherit from IUnknown (in windows.iunknown) and you're there. You don't have to use the windows.iunknown one, any interface you define called IUnknown will have the same effect.
 If it's already the case, then it should be a piece of cake. The only 
 thing
 would be to write a D interface :
 // In D
 interface iUnknown {
 int AddRef();
 int Release();
 }

 Now the methods of the interfaces all use __stdcall as calling convention,
 although it could be changed if it's necessary.
Using extern (Windows) will give a function __stdcall linkage. But any class that derives from IUknown will have __stdcall linkage by default.
Dec 28 2005
prev sibling parent Pierre Renaux <Pierre_member pathlink.com> writes:
Hi,

Thanks, that sounds good, I looked in the GDC and DMD sources about that and
there's a 'com' flag that define if an interface is COM-like or not. It sets it
as being COM-like if on of the base interfaces is called IUnknown, which is fair
enought, although it's a bit dirty...

That makes the methods being called with LINKwindows (I guess that's the
__stdcall convention) and removes the offset at the begining of the vtable.

Wouldnt it be better to be able to have a flage like extern(C) or define the
interface with a special keyword ? That would be cleaner, and most importantly
allow to define other interfaces than IUnknown has being COM-like.

Most of the API relies on iUnknown as base (not IUnknown - lower case 'i'), it's
'ok' to call it IUnknown in D. But, I also have other interfaces that are base
interfaces, mainly iSerializable and iDispatch that dont derive from iUnknown.
There's only a handfull of those, I could just make them inherit from iUnknown.
But well, it would still be slicker if I could just have something like :
interface(COM) iStuff {
}

that would be much cleaner.

Anyway thanks for the fast reply, is there any place where a 'feature' like this
could be requested ?

Can I implement it myself in the DMD base ? Mainly I'm concerned about how to
get it submitted and integrated (as in make it in GDC... or ? there's no source
code for the 'standard' D compiler), doing it isnt really the issue.


- Pierre




In article <dot4aq$1pgm$1 digitaldaemon.com>, Walter Bright says...
"Pierre Renaux" <Pierre_member pathlink.com> wrote in message 
news:dot1fr$1o1t$1 digitaldaemon.com...
 Now the "tricky" part is to make sure that I can redefine the interfaces 
 in D
 and make sure that their VTable and ABI is the same as a C++ VTable.
No problem. Inherit from IUnknown (in windows.iunknown) and you're there. You don't have to use the windows.iunknown one, any interface you define called IUnknown will have the same effect.
 If it's already the case, then it should be a piece of cake. The only 
 thing
 would be to write a D interface :
 // In D
 interface iUnknown {
 int AddRef();
 int Release();
 }

 Now the methods of the interfaces all use __stdcall as calling convention,
 although it could be changed if it's necessary.
Using extern (Windows) will give a function __stdcall linkage. But any class that derives from IUknown will have __stdcall linkage by default.
Dec 28 2005