www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - DLLs with COM interface

reply Henrik <zodiachus gmail.com> writes:
Hello!


I was reading up on http://www.digitalmars.com/d/dll.html#com regarding 
how to call DLLs with a COM interface, since this is exactly what I am 
struggling with.

I'm trying to interface with proprietary DLLs that I know expose COM 
interfaces. Fortunately, I have the documentation for them so I know 
exactly what methods they expose.

There is, for example trtCom.dll, which exposes a trtComMgr class, which 
  has a method AboutBox(). I thought I'd start with calling that, since 
it  takes no arguments and returns nothing.

Now, it said in the article mentioned above that COM objects and D 
interfaces are virtually the same thing, so I tried this:

extern(Windows)
{
	interface MbtComMgr
	{
		void AboutBox();

	}
}

But that wasn't very popular with the D compiler. It simply said:
Error: need 'this' to access member AboutBox

What would be the proper way of accessing a COM DLL?


The article said that "The sample code includes an example COM client 
program and server DLL." What sample code is it talking about exactly? I 
looked under C:\dmd\samples\d\mydll but found nothing that looks like an 
example on this.


Cheers!

Henrik
Dec 05 2007
next sibling parent Jascha Wetzel <firstname mainia.de> writes:
Henrik wrote:
 But that wasn't very popular with the D compiler. It simply said:
 Error: need 'this' to access member AboutBox

the interface is just an abstract type, you'll always need an object that you access as such an interface. that object needs to be an instance of some class that implements the interface. usually the DLL would expose a C-style function that returns such an object. for standard COM, the DLL exposes DllGetClassObject that returns a class factory object, that can instantiate all COM objects contained in the DLL. the class factory object (that implements IClassFactory) has a CreateInstance method, that will give you object pointer for a requested interface. for more details, [1] is a good place to start. i also recommend the book Essential COM by Don Box.
 The article said that "The sample code includes an example COM client 
 program and server DLL." What sample code is it talking about exactly? I 
 looked under C:\dmd\samples\d\mydll but found nothing that looks like an 
 example on this.

you can look at my code for "seatd for scite" at [2], that plugs code navigation functionality into the scite editor using com objects. the relevant code is in src/scite/seatd_scite.dll and src/scite/scite_ext.d i'm not following COM completely here, i.e. i'm not implementing IClassFactory and the method that returns the object is not called DllGetClassObject, but it's basically COM and it covers your problem as well. [1] http://en.wikipedia.org/wiki/Component_object_model [2] http://seatd.mainia.de/
Dec 05 2007
prev sibling next sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Henrik" <zodiachus gmail.com> wrote in message 
news:fj617q$15qk$1 digitalmars.com...
 Hello!


 I was reading up on http://www.digitalmars.com/d/dll.html#com regarding 
 how to call DLLs with a COM interface, since this is exactly what I am 
 struggling with.

 I'm trying to interface with proprietary DLLs that I know expose COM 
 interfaces. Fortunately, I have the documentation for them so I know 
 exactly what methods they expose.

 There is, for example trtCom.dll, which exposes a trtComMgr class, which 
 has a method AboutBox(). I thought I'd start with calling that, since it 
 takes no arguments and returns nothing.

 Now, it said in the article mentioned above that COM objects and D 
 interfaces are virtually the same thing, so I tried this:

 extern(Windows)
 {
 interface MbtComMgr
 {
 void AboutBox();

 }
 }

 But that wasn't very popular with the D compiler. It simply said:
 Error: need 'this' to access member AboutBox

 What would be the proper way of accessing a COM DLL?

COM interfaces have to inherit from IUnknown. IUnknown is "magic" and the compiler treats it specially. Furthermore, I think you should put the extern(Windows) on the inside of the interface, as I don't think putting it on the outside will affect the calling conventions of the things on the inside. (Putting it on the outside won't do much of anything, actually, except maybe change the name mangling of the interface.) So you'll have: import std.c.windows.com; interface MbtComMgr : IUnknown { extern(Windows): void AboutBox(); } :)
Dec 05 2007
prev sibling next sibling parent reply BLS <nanali nospam-wanadoo.fr> writes:
have a look at :
http://www.dsource.org/projects/juno/wiki/TypeLibraryImporter

you'll find worthfull COM information and a nice tool to automate this task.
HTH Bjoern

Henrik schrieb:
 Hello!
 
 
 I was reading up on http://www.digitalmars.com/d/dll.html#com regarding 
 how to call DLLs with a COM interface, since this is exactly what I am 
 struggling with.
 
 I'm trying to interface with proprietary DLLs that I know expose COM 
 interfaces. Fortunately, I have the documentation for them so I know 
 exactly what methods they expose.
 
 There is, for example trtCom.dll, which exposes a trtComMgr class, which 
  has a method AboutBox(). I thought I'd start with calling that, since 
 it  takes no arguments and returns nothing.
 
 Now, it said in the article mentioned above that COM objects and D 
 interfaces are virtually the same thing, so I tried this:
 
 extern(Windows)
 {
     interface MbtComMgr
     {
         void AboutBox();
 
     }
 }
 
 But that wasn't very popular with the D compiler. It simply said:
 Error: need 'this' to access member AboutBox
 
 What would be the proper way of accessing a COM DLL?
 
 
 The article said that "The sample code includes an example COM client 
 program and server DLL." What sample code is it talking about exactly? I 
 looked under C:\dmd\samples\d\mydll but found nothing that looks like an 
 example on this.
 
 
 Cheers!
 
 Henrik

Dec 05 2007
parent Henrik <zodiachus gmail.com> writes:
That is a very nifty little tool! After resolving the interdependencies 
between the DLLs, the stuff actually runs! Excellent, thanks.




BLS wrote:
 have a look at :
 http://www.dsource.org/projects/juno/wiki/TypeLibraryImporter
 
 you'll find worthfull COM information and a nice tool to automate this 
 task.
 HTH Bjoern

Dec 17 2007
prev sibling parent Mike <vertex gmx.at> writes:
On Wed, 05 Dec 2007 12:15:10 +0100, Henrik <zodiachus gmail.com> wrote:

 Hello!


 I was reading up on http://www.digitalmars.com/d/dll.html#com regardin=

 how to call DLLs with a COM interface, since this is exactly what I am=

 struggling with.

 I'm trying to interface with proprietary DLLs that I know expose COM  =

 interfaces. Fortunately, I have the documentation for them so I know  =

 exactly what methods they expose.

 There is, for example trtCom.dll, which exposes a trtComMgr class, whi=

   has a method AboutBox(). I thought I'd start with calling that, sinc=

 it  takes no arguments and returns nothing.

 Now, it said in the article mentioned above that COM objects and D  =

 interfaces are virtually the same thing, so I tried this:

 extern(Windows)
 {
 	interface MbtComMgr
 	{
 		void AboutBox();

 	}
 }

 But that wasn't very popular with the D compiler. It simply said:
 Error: need 'this' to access member AboutBox

 What would be the proper way of accessing a COM DLL?

An interface on its own is just a contract saying how the actual instanc= e = will be layed out in memory and how it will be called (usually extern = (Windows) for COM). You need an actual instance, which you can get from = = Windows with the CoCreateInstance call: extern (Windows) IFooBar : IUnknown { ... } CoInitialize(null); // initialize COM before getting the = instance scope (exit) CoUninitialize(); // close COM after we're finished IFooBar instance; // this just declares a reference to the interface = IFooBar which is null at first CLSID clsid =3D ...; // you need to know the DLL's class id first! CLSCTX clsctx =3D ...; // the context, normally CLSCTX_INPROC_SERVER auto rc =3D CoCreateInstance(clsid, null, clsctx, clsid, = cast(void**)&instance); if (rc !=3D S_OK) throw new Exception("Couldn't create instance!"); /* now you can call the IFooBar instance */ instance.Release(); // release the instance The important part is to get the instance pointer from COM with = CoCreateInstance. It creates the instance and stores the pointer to it i= n = instance (that's why there's a cast(void**) in there). Deriving from = IUnknown is important too 'cause then the housekeeping is done = automatically and you just use the instance as if you'd created it with = = new. Don't forget to release the instance after you're done with it, don= 't = delete it! The definitions for CLSID etc. are in phobos and Tango, just search for = = them. If it doesn't work (like it did for me) I can recommend downloadin= g = the schooner project from dsource.org and using its win32 files - they = have every definition and they work. -Mike -- = Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Dec 06 2007