Sorry if this question seems obvious for everyone, but I am very new to COM. From the tutorial I see here http://www.codeguru.com/cpp/com-tech/activex/tutorials/article.php/c5567, it seems like every COM class created in C++ must implement its own QueryInterface, AddRef and Release. Since these methods should have basically the same implementation for any new class, I don't understand why there isn't some abstract class or whatever that implements it for the developer. I don't understand why I should re-implement the same thing that so many people have already implemented again and again (unless the tutorial is wrong and there IS something).
Thanks
FTA:
"I believe that every programmer who wishes to understand the basic principles behind COM, must write atleast one simple COM object using plain C++ , i.e. without the aid of templates and macros that comes along with MFC/ATL."
To answer your question: Yes, every COM component must implement IUnknown, it's the foundation COM is built on. However, as for the "standard pluming" for creating COM objects this is what the ATL Project Wizard is for.
If you don't want to use ATL or other helper libraries you can use the QISearch helper function that handles QueryInterface for you. AddRef and Release can be implemented in your own base class.
COM needs to work with plain C also so the windows sdk does not really go beyond the definition of the class and its methods.
Yes, every COM class must implement IUnknown, because every COM class inherits from IUnknown - that's one of the basic COM technology principles. This is usually done by using ATL - it has templates and macros for doing that rather easily and even if you don't want to use ATL you can write a template for most trivial cases (like implementing one interface) pretty easily and reuse that.
Related
Is it possible to call C++ class library from delphi 2007? What is the way of doing that? I know how to call dll function, but how to deal with class?
There are several ways to do this, but you can't use a C++ class directly. Both useful ways to achieve this require some work and are extensively described here:
Using C++ objects in Delphi (http://rvelthuis.de/articles/articles-cppobjs.html)
Update
OK, I was asked to do an update. The article describes two ways:
Writing and exposing C functions that take the C++ object as (first) parameter (the C++ type is simply passed on as opaque type in Delphi), which simply perform the functionality the class provides by calling the class methods with the right parameters. The C functions can be called from Delphi.
Writing a COM wrapper for the class. The article describes how this can be done in C++.
Details can be found in the article.
You cannot consume C++ classes from Delphi. You will need to wrap them in some other interop friendly manner. For instance:
Wrap the C++ classes with C style functions that expose the functionality.
Expose COM objects that provide the functionality.
Tomorrow I have planed to do some IDispatch related work, and I will have to create a class that supports this interface.
I have been using ATL classes for a while to create COM objects and manage COM pointers, so I would like to use them for my class as well. But research so far, and discussions with colleagues have led me to believe that I need all the heavyweight IDL stuff even if I want to create a simple class with one property or method.
If that's the case I'll probably resort to writing everything from scratch, but I still hope I'm missing something. Is there a template I've missed?
ATL has an IDispatchImpl class.
I have a pre-existing c++ object model which represents the business layer tier of an application. I want to be able to expose the object model to applications written in other languages i.e vbscript, VB, javascript etc. I believe the best way of doing this is to wrap the business objects with a COM layer.
What fast and effective methods are there for doing this. Any advice, links to practical "How to" documentation would be very much appreciated.
Because I'm starting a bounty on this , here's a few extra guidelines for potential bounty hunters :-
1)I've decided on an ATL approach
2)I'm now specifically looking for links to really good "how to and quickly" documentation on wrapping a pre-existing c++ object model to make it useable by a scripting language like javascript
3) Something with small working examples showing me what code needs to be added to what files, e.g what goes into the cpp , idl and hpp/h etc. It' must include an example I can compile test and change to get a better understanding.
Addendum .....
Further context. For me this is a re-visit to COM after about 10 years. I did MFC and ATL COM for the 3 years prior to 2000. I understand what COM is , the principles used to implement it in C++, threading models etc. Any "how to and quickly" documentation will not be leading me blindly and glazing over important principles, more it'll be a guided re-learning experience.
If I had more time I'd dig into "developer's workshop to COM and ATL 3.0" by Troelsen, a very good book but it's a very slow kick (re)start.
Further context following comments...........
Keeping it as simple as possible , Single-Threaded Apartment model and an inprocess dll.
I find a good collection of articles for beginner in http://www.codeproject.com/KB/COM/index.aspx?#COM/DCOM/COM+%20-%20Beginners. This are:
http://www.codeproject.com/KB/COM/hellocom.aspx, http://www.codeproject.com/KB/COM/comintro2.aspx,
http://www.codeproject.com/KB/COM/comintro.aspx, http://www.codeproject.com/KB/COM/com_server_without_mfc_atl.aspx, http://www.codeproject.com/KB/COM/com_in_c1.aspx
But if you start to program a COM objects it's very important to understand threading models of COM. This is explain very good here
http://www.codeproject.com/KB/COM/CCOMThread.aspx, http://www.codeproject.com/KB/COM/CCOMThread2.aspx
But I decide to answer you because I want suggest to choose a little other modern way. COM technology is very old. Dot NET has all the features inside and will permanently developed. So I find an approach from Building COM Servers in .NET the most interesting. You write your COM full in C# divide the development of your COM objects in two parts:
You write interface only assembly without any implementation and register it.
You develop a .NET classes which implements this COM interface.
You can look at the more easy version of the same in http://www.codeproject.com/KB/COM/COMinDotNet.aspx, http://www.codeproject.com/KB/cs/CreateActiveXDotNet.aspx, http://msdn.microsoft.com/en-us/library/ms973807.aspx, but I recommend you the way "Building COM Servers in .NET" described in http://www.codeproject.com/KB/COM/BuildCOMServersInDotNet.aspx.
UPDATED after the comment: Sorry, but you are searching an easy way to solve a complex problem. It is impossible.
It is very important to understand, that despite of quasi similarity there are a lot of principal differences between object oriented C++ and COM. It’s important to understand, that COM isn't an object-oriented language but a binary protocol. A software component (COM objects) is a binary unit of reusable code. It solves a lot of problems existing in separate compilation of modules of programs designed based on object-oriented approach.
If, for example, somebody inherited you classes and you change later some private members, it makes influence to the all inherited classes. The full code used your C++ objects must be recompiled at least because sizeof(object) has been changed. Such problem not exists in COM, because all who use your objects don’t inherit your object classes. One uses your objects through interfaces, which signature and sizeof() will not be changed after you modify some private members of your base classes. You can read online some very good examples in the first chapter of the classic book "Essential COM" by Don Box: http://books.google.co.uk/books?id=kfRWvKSePmAC&dq=essential+com&printsec=frontcover&source=bn&hl=en&sa=X&oi=book_result&resnum=6&ct=result. I recommend you also to read a small article http://edndoc.esri.com/arcobjects/9.0/ArcGISDevHelp/DevelopmentEnvs/COM/IntroToCOM.htm to understand more differences between COM and C++ objects.
If you rewrite your C++ objects as a COM objects you have to choose threading model, you have to understand how to write a thread safe program or you have to use Single-Threaded Apartment model. All your objects will be exist (allocated and running) in a separate thread. If you choose Out-Of-Process COM object (an exe with all your objects will be created), then a new process will be created. If somebody calls a method of your object a marshaling of all parameters will be done. Marshaling of parameters means allocation of memory in another thread and copying of all parameter to the thread.
All this things which I described before are not a terms of C++ objects. I write this only to clear that COM really not the same as C++ object model.
So to wrap your existing C++ objects you have to define some pure virtual classes – interfaces which you implement in your objects. This interface must be in written in IDL/MIDL (Microsoft Interface Definition Language). This is the most important thing! Then you have to implement these interfaces as COM coclasses using your existing C++ classes.
I am sure if you do these work in .NET you have not be required to study a lot of implementation details typically needed to know for COM developer. You just define an Interface in C#/C++ (a pure virtual class) and compile it. You can generate a private key for strong signed assembly inside of Visual Studio. Just go in the project settings in "Signing" part and select "Sign the assembly" then choose "New" strong name key file. It’s all. With this way you full define a COM interface. A MIDL version of the interface will be generated for you.
Then you create a new project in C# or C++ and declare classes which inherit the interface which you define before. During implementing of this interface you can use your entire existing C++ object. So you will be able quickly rich your targets. Just follow the way described in details in http://www.codeproject.com/KB/COM/BuildCOMServersInDotNet.aspx. With this way you will not have to study a lot of technical details which you have to know for classical COM implementation in C++. And you will study a modern .NET instead of studying the old and de facto dead (or not further developed) COM.
Sorry for the long answer.
http://www.lambdasoft.dk/Comet/index.htm
Comet is language binding between COM and C++. It allows you to do both COM client and COM server programming, without any dependency on either ATL or MFC. In other words Comet is a replacement for ATL.
I am quite new to COM so the question may seem naive.
Q1. About Windows DLL
Based on my understanding, a Windows DLL can export functions, types(classes) and global variables. Is this understanding all right?
Q2. About COM
My naive understanding is that: a COM DLL seems to be just a new logical way to organize the functions and types exported by a standard Windows DLL. A COM DLL exports both functions such as DllRegisterServer() and DllGetClassObject(), and also the Classes which implements the IUnknown interface. Is this understanding all right?
Q3. *.def & *.idl
*.def is used to define the functions exported by a Windows DLL in the traditional way, such as DllGetClassObject().
*.idl is used to define the interface implemented by a COM coclass.
Thanks in advance.
Think of COM as a binary compatible way to share interfaces across DLL boundaries. C++ classes can't easily be exported from DLLs because of the non-standard name mangling done between various compiler versions. COM allows code in one DLL or executable, to create an implementation of an interface from another DLL or EXE as long as that implementation follows a defined interface and calling convention. This is what allows a COM class to be written in C# and invoked from C++, Python, and many other COM-aware languages.
COM interfaces are just standard C++ classes containing all pure virtual functions and derived from IUnknown. IUnknown is a pre-defined interface that all compliant COM interfaces must derive from that provides common facilities like reference counting and the ability to query whether an object implements a particular interface.
DLLs that wish to advertise the fact they can create implementations of COM interfaces do so by exporting 4 functions:
DllGetClassObject => Return a class factory of a requested interface
DllCanUnloadNow => Whether all instances handed out have since been released
DllRegisterServer => Register the types this DLL supplies in the registry
DllUnregisterServer => Unregister this DLL and its types from the registry
So to answer your questions:
Q1. About Windows DLL Based on my understanding, a Windows DLL can export functions,
types(classes) and global variables. Is this understanding all right?
DLLs can export functions and classes (not sure about global variables, but you don't want to be exporting them DLLs even if you can! :-) ) However, exported classes will be name mangled and hence only usable by other DLLs or EXEs that happen to have the same name mangling (not a good way to do business). Functions with C-style calling convention are not name mangled and hence can be exported and called from elsewhere without problems.
Q2. A COM DLL exports both functions such as DllRegisterServer() and DllGetClassObject(),
and also the Classes which implements the IUnknown interface. Is this understanding all
right?
Halfway, there are 4 functions to export to be a full COM compliant DLL (shown above). You can search MSDN for any of those names to see the full signatures fro them. Your implementation for DllGetClassObject is going to be the main one which outside parties will use. They can use that to get an IClassFactory to an interface your DLL provides, and then use that to create an instance.
COM is a large and complicated beast, but its foundations are fairly straightforward. You can also check out this link COM Intro for some more info. Good luck!
To add on to cpalmer's nice answer, there's no particular reason why you need to use the registry and the four recommended functions to export COM from your DLL.
You could use a registry-free COM, or COM-lite approach, where you simply export factory methods, such as
__declspec(dllexport) void MyDllCreateFoo(IFoo ** ppFoo);
DLL users would call your factory to create your class CMyFoo which implements IFoo. What DllRegisterServer et. al. do is allow CMyFoo and other classes to be looked up in the registry, among other things.
Q3: You are correct in fact, if not in spirit. .def files and .idl files are pretty different beasts. .def files are used by the linker only, and aren't even necessary - you can export all the functions you want using
__declspec(dllexport) void foo() {
}
inside your C++ code.
.idl files are used to generate C++ headers (.h files) which are included both by the DLL as well as its clients. It generates the interfaces plus some glue code that does things like parameter mashalling.
Again, you don't techincally need to use IDL to use COM, but it can make things more convenient.
The reason I'm breaking it down like this is to illustrate that COM is not a big monolithic thing, but rather a really small thing with a bunch of stuff built up around it that you could opt to use, or not, to taste.
You have it all exactly right so far. The only bit I would clarify is "the Classes which implements the IUnknown interface." A class is represented by an object that implements the IClassFactory interface. You can get such a class factory by calling DllGetClassObject in a DLL, and then you can ask the class factory to make an object of the class. This is similar to many other object-oriented systems: there is a variety of objects that represent classes and which can be used to manufacture instances.
Other useful facts about COM:
There is a small but complicated library of helper functions, mostly named with the prefix Co. It is these which actually load the DLLs, locate the exported functions and call them. Client code would not normally call the DLL exports directly (although it is a fairly straightforward matter to write your own hosting system for simple in-process COM objects).
There is an important interface IDispatch which adds another layer of abstraction such that it is possible to dynamically identify methods to call on the object, using a string to find the method and passing an array of argument values. This allows scripting languages to call COM objects safely (i.e. in a way that tolerates mistakes by the programmer instead of crashing).
There is a more complex "marshalling" system for allowing objects to be called from other threads, other processes or even other computers; in its remote (and security-aware) for form it was called DCOM. It did not succeed on anything like the scale that other COM usages did.
The cross-process support was the basis of OLE2, a gimmick that every application rushed to support in the early 1990s, most of them implementing the (very complicated) interfaces wrongly and so crashing all over the place.
Far more successful were OLE Controls, which were technically a lot simpler (not using the marshalling) and which offered a way to extend Visual Basic.
There is at least one widely distributed COM-inspired system that is not compatible with COM but shares exactly the same concepts (at least the simple stuff), which is called XPCOM and is the basis of the Mozilla Firefox Web browser.
If you use COM pervasively, you will have a great way to integrate with the .NET framework, as it includes superb interoperability with COM. But you must follow the rules of COM precisely: AddRef/Release must work exactly as defined, so an object must never be destroyed while its reference count is greater than zero, it must be possible to use QueryInterface to find IUnknown from any interface, and from there to get back to the original interface, the IUnknown obtained from any interface must always have the same memory address for the lifetime of the object (so it can be used for identity comparison). So for example: don't create COM objects on the stack, and don't return separate objects from QueryInterface (that is, objects that have their own QueryInterface that returns different interfaces).
A major gotcha with COM is that it has at least two standard ways of representing strings. Neither uses reference counting. Why they never defined an IString interface is beyond me, but they didn't.
You'll go insane if you try to write COM code without smart pointers to hold references, or without a base class to help you implement interfaces, e.g. class MyClass : COM::Object<IThis, IThat> {...)
I have an unmanaged class that I'm trying to dllexport from a managed DLL file. I'm trying to use the unmanaged class in another managed DLL file. However, when I try to do this I get link errors.
I've done this lots of times with unmanaged DLL files, so I know how that works. I know how to use "public ref", etc. in managed classes.
Is there some flag somewhere I need to set? Or do I have to do some DllImport magic?
This is on .NET 2.0 and Visual Studio 2005.
If you want to use an unmanaged class from managed code, you can:
Use some nasty P/Invoke to load the class member functions (constructor, destructor, etc.) and make a nastier managed wrapper class to call the "real" member functions. This gets even worse when there are virtual methods involved.
The second option (which in my opinion is better) is to write a C++/CLI wrapper class (you mentioned that you're familiar with this) that is a simple proxy to the unmanaged class. For every member function you have in the unmanaged class you'll have a similar one in your proxy class. Then it's a simple case of adding a reference to that DLL from your managed project, and you'll be able to use your class as any other .NET class. Take into consideration that you'll run into more work if your class exposes other unmanaged stuff (those that can't be marshalled).
If you need more information on the second option, I could look up some old links that explained this technique more.
You need to use an interop assembly for unmanaged libraries or COM components. Here is a link with good information regarding this.
If it is a COM DLL file then you can use COM .NET interoperability. Stack Overflow question Is there a best practice for accessing C++ native COM functions to interop from C#? is another question which answers this.