i have a legacy COM components, as part of upgradation i derived from an existing interface
interface1
{
few methods
}
interface2 :public interface1
{
new methods
}
there was an old review comment not to do this..instead have inteface2 has separate one not deriving from the base, as it part of the same CoClass...there is no need to duplicate any code...
review comment :
Scripting languages are interpreted languages and are naturally polymorphic as all methods are late bound. All variables are typeless (VARIANT is typeless).
However, there is a separate problem concerning scripting languages. Scripting languages do not use the virtual function table in order to invoke methods on a COM object but instead invoke methods via the IDispatch interface. Unfortunately IDispatch can only be associated with one custom interface.
All methods accessed via IDispatch must be part of the custom interface
can anyone explain ...does he mean to say that getidsofnames will not be able to return the correct ID ? or is it something else
It is accurate enough, a coclass can implement multiple interfaces. But one is "special", it is the one that's attributed with [default] in the IDL. Scripting languages can only use that default interface, they don't have a mechanism to retrieve another interface. Or in other words, they can't call QueryInterface(). Mostly because they don't support the notion of interfaces or casting or multiple inheritance at all in their language design. Intentionally, scripting languages are supposed to be easy to use.
So if interface1 was originally the default interface then the scripting programmer can never use the added interface2 methods. You'll want to have a look at this SO post to see the consequences.
You can keep COM interfaces backwards compatible with old client programs by only ever appending new methods and never change the order or arguments of the old ones. It is risky, an updated client program that accidentally meets an old version of your component will go up in flames in a very bad way. Usually very hard to diagnose, pure DLL Hell. Only truly safe way is to assign new [uuid]s, forcing the client program to be recompiled. If you also change the name or install location of the DLL then they can live side-by-side.
Related
I have added a new interface IAEx which is extended from the existing interface IA (derived from IDispatch).
What are the things to change in idl?
I have changed the coclass definitions to inherit from the new one.
I changed the coclass entry in idl which was like this earlier.
(I need the deafult interface as new one)
coclass CAx
{
[default] interface IA
[default, source] dispinterface IAEvents;
};
and changed to
coclass CAx
{
[default] interface IAEx
[default, source] dispinterface IAEvents;
};
can I change the deafualt interafce?
coclass definition change.
old one
class ATL_NO_VTABLE CAx:
...
public CCIDispatchImpl<IA, &IID_IA, &LIBID_CCALib>,
new one.
class ATL_NO_VTABLE CAx:
...
public CCIDispatchImpl<IAEx, &IID_IAEx, &LIBID_CCALib>,
Is this fine?
COM MAP entries modification:
Old one:
COM_INTERFACE_ENTRY(IA)
COM_INTERFACE_ENTRY2(IDispatch,IA)
new one:
COM_INTERFACE_ENTRY(IAEx)
COM_INTERFACE_ENTRY2(IDispatch,IAEx)
Do I need to add old interface also in COM MAP?
No, this is a drastically breaking change to client programs. Golden rule #1 to keep in mind is that names are quite immaterial in COM, only uuids matter. Rule #2 is that COM components have machine scope, modifying a component affects every program on the machine that uses the component. Another way to say that is that COM has a strong DLL Hell problem.
So the first thing that will happens when you install your component on a machine is that every program that uses it will stop to work. They are still looking for the "IA" interface uuid and it is not there anymore. They fail with E_NOINTERFACE. Only way to avoid that is to get the client programs recompiled with your new type library and deploy them at the exact same time your updated COM component is deployed. This is often very hard to arrange since they don't have programmers or companies in common. Usually only the user can do this, they very rarely know how to do this correctly or know how to troubleshoot failure.
If you want your update to be backwards compatible then you must add a new interface to your coclass. It cannot be the [default] interface since existing client programs expect the legacy interface as the default. That however causes a new problem, client runtimes that use IDispatch often don't support anything but a single default interface. Usually because they don't have a notion of interfaces as a primary language construct. In other words, your client programmer has no way to call IUnknown::QueryInterface() and therefore cannot use your new interface at all. So not a general solution.
It is technically possible to violate the interfaces are immutable rule in COM. You can add new methods to the end of the IDispatch interface. Existing client code is unaware of them so will never call them and continue to operate correctly both with the old and the new version of your component. Assuming that you know how to maintain the legacy methods without causing a breaking behavior change, often harder than it looks. There is still a DLL Hell problem though, the world implodes when an updated version of the client code meets the old version of your component. This might seem unlikely at first sight but this tends to go wrong much later, when the machine is replaced or re-imaged. Very ugly scenario, the runtime failure is impossible to diagnose and anybody originally involved is not around anymore or doesn't remember the details.
Only truly safe way to do this is to create a new version. Modify all the uuids (LIBID, CLSID and IID) and change the DLL filename. Now the old and new version can co-exist and the client programmer can use your new version at his leisure. There might still be a deployment problem but the failure is easy to diagnose, the client program fails with "Class not registered".
You should include the old interface in the COM MAP as well as if a client attempts to QueryInterface for the old interface it should receive a useful result and not an error. Add COM_INTERFACE_ENTRY2(IA, IAEx).
Otherwise it looks like you have everything. We add both interfaces into the coclass entry in the IDL file but I don't thing anything really uses that. ie:
coclass Ax
{
[default] interface IAEx;
interface IA;
};
Whether it is fine or not depends on what is the goal exactly. Replacing interface is fine on its own, if you are concerned with not breaking compatibility with existing client, the most important thing is that your server still implements old interface IA. You should list the interface on the COM MAP (since you mentioned that IAEx is inherited from IA, you might need a COM_INTERFACE_ENTRY_IID macro):
COM_INTERFACE_ENTRY(IAEx)
COM_INTERFACE_ENTRY_IID(__uuidof(IA), IAEx) //COM_INTERFACE_ENTRY(IA)
COM_INTERFACE_ENTRY2(IDispatch, IAEx)
This way your server implements both IAEx and IA. Inheriting interfaces one from another is the thing I would rather suggest against, but you have what you have.
Updating coclass (as suggested in answer by patthoyts) makes update cleaner and is worth doing as well, however it is more important for rebuilding the clients rather than keeping compatibility with already existing built code: tools importing type library information will be able to see both interfaces if they at all care and are capable to handle non-default interfaces there.
I am using bada and refer to the tutorial here, which begins:
class MainForm:
public Osp::Ui::Controls::Form,
public Osp::Ui::IActionEventListener,
public Osp::Ui::ITouchEventListener
{
I am running code where I recently removed the public specifier to cut down on my public API. You'll see that the functions implementing those interfaces where all also declared publicly, for which I saw no need and made private. I would do this without hesitation when implementing my own interfaces when those interfaces may provide more access than I would wish regular clients of my concrete class to receive.
What is the reason for making them public, what am I missing?
I guess it is advocated to aid extensibility, but for a dev making apps not libraries I would challenge this wisdom.
If Form, IActionEventListener and ITouchEventListener already support many usable methods, in most cases why hide them? On the contrary: if you hide them and in the future someone will need them, it will be harder for you to maintain the class because you'll need to provide them again.
If you need to hide the parent's methods, there's another way to do this: instead of inheriting, enclose the "parent" as a field in your new class.
In some languages such as C#, public inheritance is the only option.
For me private inheritance of "interfaces" is a non sens.
The interface of an object is its set of public methods. As llya said, if you want to use the functionalities provided by a class internally, use object composition. If you want to provide a subset of the interface, then either compose or simply declare a more restrictive interface.
If the "interface" and the functions taking object from this interface are in a third party library then its means that the developers wanted to force you to implement every methods, so you have to provide them.
Run into a bit of an issue, and I'm looking for the best solution concept/theory.
I have a system that needs to use objects. Each object that the system uses has a known interface, likely implemented as an abstract class. The interfaces are known at build time, and will not change. The exact implementation to be used will vary and I have no idea ahead of time what module will be providing it. The only guarantee is that they will provide the interface. The class name and module (DLL) come from a config file or may be changed programmatically.
Now, I have all that set up at the moment using a relatively simple system, set up something like so (rewritten pseudo-code, just to show the basics):
struct ClassID
{
Module * module;
int number;
};
class Module
{
HMODULE module;
function<void * (int)> * createfunc;
static Module * Load(String filename);
IObject * CreateClass(int number)
{
return createfunc(number);
}
};
class ModuleManager
{
bool LoadModule(String filename);
IObject * CreateClass(String classname)
{
ClassID class = AvailableClasses.find(classname);
return class.module->CreateObject(class.number);
}
vector<Module*> LoadedModules;
map<String, ClassID> AvailableClasses;
};
Modules have a few exported functions to give the number of classes they provide and the names/IDs of those, which are then stored. All classes derive from IObject, which has a virtual destructor, stores the source module and has some methods to get the class' ID, what interface it implements and such.
The only issue with this is each module has to be manually loaded somewhere (listed in the config file, at the moment). I would like to avoid doing this explicitly (outside of the ModuleManager, inside that I'm not really concerned as to how it's implemented).
I would like to have a similar system without having to handle loading the modules, just create an object and (once it's all set up) it magically appears.
I believe this is similar to what COM is intended to do, in some ways. I looked into the COM system briefly, but it appears to be overkill beyond belief. I only need the classes known within my system and don't need all the other features it handles, just implementations of interfaces coming from somewhere.
My other idea is to use the registry and keep a key with all the known/registered classes and their source modules and numbers, so I can just look them up and it will appear that Manager::CreateClass finds and makes the object magically. This seems like a viable solution, but I'm not sure if it's optimal or if I'm reinventing something.
So, after all that, my question is: How to handle this? Is there an existing technology, if not, how best to set it up myself? Are there any gotchas that I should be looking out for?
COM very likely is what you want. It is very broad but you don't need to use all the functionality. For example, you don't need to require participants to register GUIDs, you can define your own mechanism for creating instances of interfaces. There are a number of templates and other mechanisms to make it easy to create COM interfaces. What's more, since it is a standard, it is easy to document the requirements.
One very important thing to bear in mind is that importing/exporting C++ objects requires all participants to be using the same compiler. If you think that ever could be a problem to you then you should use COM. If you are happy to accept that restriction then you can carry on as you are.
I don't know if any technology exists to do this.
I do know that I worked with a system very similar to this. We used XML files to describe the various classes that different modules made available. Our equivalent of ModuleManager would parse the xml files to determine what to create for the user at run time based on the class name they provided and the configuration of the system. (Requesting an object that implemented interface 'I' could give back any of objects 'A', 'B' or 'C' depending on how the system was configured.)
The big gotcha we found was that the system was very brittle and at times hard to debug/understand. Just reading through the code, it was often near impossible to see what concrete class was being instantiated. We also found that maintaining the XML created more bugs and overhead than expected.
If I was to do this again, I would keep the design pattern of exposing classes from DLL's through interfaces, but I would not try to build a central registry of classes, nor would I derive everything from a base class such as IObject.
I would instead make each module responsible for exposing its own factory functions(s) to instantiate objects.
I'm looking to implement a custom implementation of COM in C++ on a UNIX type platform to allow me to dynamically load and link object oriented code. I'm thinking this would be based on a similar set of functionality that POSIX provides to load and call dll's ie dlopen, dlsym and dlclose.
I understand that the general idea of COM is that you link to a few functions ie QueryInterface, AddRef and Release in a common dll (Kernel32.dll) which then allows you to access interfaces which are just a table of function pointers encapsulated with a pointer to the object for which the function pointers should be called with. These functions are exposed through IUnknown which you must inherit off of.
So how does this all work? Is there a better way to dynamically link and load to object oriented code? How does inheritance from a dll work - does every call to the base class have to be to an exposed member function i.e private/protected/public is simply ignored?
I'm quite well versed in C++ and template meta-programming and already have a fully reflective C++ system i.e member properties, member functions and global/static functions that uses boost.
A couple of things to keep in mind:
The power of COM comes largely from the IDL and the midl compiler. It allows a verry succint definition of the objects and interfaces with all the C/C++ boilerplate generated for you.
COM registration. On Windows the class IDs (CLSID) are recorded in the registry where they are associated with the executable. You must provide similar functionality in the UNIX environment.
The whole IUnknown implementation is fairly trivial, except for QueryInterface which works when implemented in C (i.e. no RTTI).
A whole another aspect of COM is IDispatch - i.e. late bound method invocation and discovery (read only reflection).
Have a look at XPCOM as it is a multi-platform COM like environment. This is really one of those things you are better off leveraging other technologies. It can suck up a lot of the time better spent elsewhere.
I'm looking to implement a custom implementation of COM in C++ on a UNIX type platform to allow me to dynamically load and link object oriented code. I'm thinking this would be based on a similar set of functionality that POSIX provides to load and call dll's ie dlopen, dlsym and dlclose.
At its simplest level, COM is implemented with interfaces. In c++, if you are comfortable with the idea of pure virtual, or abstract base classes, then you already know how to define an interface in c++
struct IMyInterface {
void Method1() =0;
void Method2() =0;
};
The COM runtime provides a lot of extra services that apply to the windows environment but arn't really needed when implementing "mini" COM in a single application as a means to dynamically link to a more OO interface than traditionally allowed by dlopen, dlsym, etc.
COM objects are implemented in .dll, .so or .dylib files depending on your platform. These files need to export at least one function that is standardized: DllGetClassObject
In your own environment you can prototype it however you want but to interop with the COM runtime on windows obviously the name and parameters need to conform to the com standard.
The basic idea is, this is passed a pointer to a GUID - 16 bytes that uniquely are assigned to a particular object, and it creates (based on the GUID) and returns the IClassFactory* of a factory object.
The factory object is then used, by the COM runtime, to create instances of the object when the IClassFactory::CreateInstance method is called.
So, so far you have
a dynamic library exporting at least one symbol, named "DllGetClassObject" (or some variant thereof)
A DllGetClassObject method that checks the passed in GUID to see if and which object is being requested, and then performs a "new CSomeObjectClassFactory"
A CSomeObjectClassFactory implementation that implements (derives from) IClassFactory, and implements the CreateInstance method to "new" instances of CSupportedObject.
CSomeSupportedObject that implements a custom, or COM defined interface that derives from IUnknown. This is important because IClassFactory::CreateInstance is passed an IID (again, a 16byte unique id defining an interface this time) that it will need to QueryInterface on the object for.
I understand that the general idea of COM is that you link to a few functions ie QueryInterface, AddRef and Release in a common dll (Kernel32.dll) which then allows you to access interfaces which are just a table of function pointers encapsulated with a pointer to the object for which the function pointers should be called with. These functions are exposed through IUnknown which you must inherit off of.
Actually, COM is implemented by OLE32.dll which exposes a "c" api called CoCreateInstance. The app passed CoCreateInstance a GUID, which it looks up in the windows registry - which has a DB of GUID -> "path to dll" mappings. OLE/COM then loads (dlopen) the dll, calls its DllGetClassObject (dlsym) method, passing in the GUID again, presuming that succeeds, OLE/COM then calls the CreateInstance and returns the resulting interface to app.
So how does this all work? Is there a better way to dynamically link and load to object oriented code? How does inheritance from a dll work - does every call to the base class have to be to an exposed member function i.e private/protected/public is simply ignored?
implicit inheritance of c++ code from a dll/so/dylib works by exporting every method in the class as a "decorated" symbol. The method name is decorated with the class, and type of every parameter. This is the same way the symbols are exported from static libraries (.a or .lib files iirc). Static or dynamic libraries, "private, protected etc." are always enforced by the compiler, parsing the header files, never the linker.
I'm quite well versed in C++ and template meta-programming and already have a fully reflective C++ system i.e member properties, member functions and global/static functions that uses boost.
c++ classes can typically only be exported from dlls with static linkage - dlls that are loaded at load, not via dlopen at runtime. COM allows c++ interfaces to be dynamically loaded by ensuring that all datatypes used in COM are either pod types, or are pure virtual interfaces. If you break this rule, by defining an interface that tries to pass a boost or any other type of object you will quickly get into a situation where the compiler/linker will need more than just the header file to figure out whats going on and your carefully prepared "com" dll will have to be statically or implicitly linked in order to function.
The other rule of COM is, never pass ownership of an object accross a dynamic library boundary. i.e. never return an interface or data from a dll, and require the app to delete it. Interfaces all need to implement IUnknown, or at least a Release() method, that allows the object to perform a delete this. Any returned data types likewise must have a well known de-allocator - if you have an interface with a method called "CreateBlob", there should probably be a buddy method called "DeleteBlob".
To really understand how COM works, I suggest reading "Essential COM" by Don Box.
Look at the CORBA documentation, at System.ComponentModel in the sscli, the XPCOM parts of the Mozilla codebase. Miguel de Icaza implemented something like OLE in GNOME called Bonobo which might be useful as well.
Depending on what you're doing with C++ though, you might want to look at plugin frameworks for C++ like Yehia. I believe Boost also has something similar.
Edit: pugg seems better maintained than Yehia at the moment. I have not tried it though.
The basic design of COM is pretty simple.
All COM objects expose their functionality through one or more interfaces
All interfaces are derived from the IUnknown interface, thus all interfaces have
QueryInterface, AddRef & Release methods as the first 3 methods of their virtual
function table in a known order
All objects implement IUnknown
Any interface that an object supports can be queried from any other interface.
Interfaces are identified by Globally Unique Identifiers, these are IIDs GUIDs or CLSIDs, but they are all really the same thing. http://en.wikipedia.org/wiki/Globally_Unique_Identifier
Where COM gets complex is in how it deals with allowing interfaces to be called from outside the process where the object resides. COM marshalling is a nasty, hairy, beast. Made even more so by the fact that COM supports both single threaded and multi-threaded programming models.
The Windows implementaion of COM allows objects to be registered (the original use of the Windows registry was for COM). At a minimum the COM registry contains the mapping between the unique GUID for a COM object, and the library (dll) that contains it's code.
For this to work. DLLs that implement COM objects must have a ClassFactory - an entry point in the DLL with a standard name that can be called to create one of the COM objects the DLL implements. (In practice, Windows COM gets an IClassFactory object from this entry point, and uses that to create other COM objects).
so that's the 10 cent tour, but to really understand this, you need to read Essential COM by Don Box.
You may be interested in the (not-yet)Boost.Extension library.
Application is written in delphi 2010 and the underlying dll is a C++ dll.
In ideal case, when your application is in C++; The dll makes a callback to an application when an event occurs. The callback is implemented through an interface. Application developers implements the abstract c++ class and pass the object to the dll. The dll will then make a callback to a member function of your implemented class. A classic callback pattern it is.
But how do I pass a delphi object to the dll for it to make a callback.
I wouldn't really call that ideal. It is selfish and short-sighted to make a DLL that requires its consumers to use the same compiler as the DLL used. (Class layout is implementation-defined, and since both modules need to have the same notion of what a class is, they need to use the same compiler.)
Now, that doesn't mean other consumers of the DLL can't fake it. It just won't be as easy for them as the DLL's designer intended.
When you say the callback is implemented through an interface, do you mean a COM-style interface, where the C++ class has nothing but pure virtual methods, including AddRef, Release, and QueryInterface, and they all use the stdcall calling convention? If that's the case, then you can simply write a Delphi class that implements the same interface. There are many examples of that in the Delphi source code and other literature.
If you mean you have a non-COM interface, where the C++ class has only pure virtual methods, but not the three COM functions, then you can write a Delphi class with the same layout. Duplicate the method order, and make sure all the methods are virtual. The Delphi VMT has the same layout as most C++ vtables on Windows implementations, at least as far as the function-pointer order is concerned. (The Delphi VMT has a lot of non-method data as well, but that doesn't interfere with the method addresses.) Just be sure you maintain clear ownership boundaries. The DLL must never attempt to destroy the object; it won't have a C++-callable destructor that the delete operator could invoke.
If you mean that you have an arbitrary C++ class that could include data members, constructors, or non-pure methods, then your task is considerably more difficult. Follow up if this is the case; otherwise, I'd rather not address it right now.
Overall, I'll echo Mason's advice that the DLL should use plain C-style callback functions. A good rule of thumb is that if you stick to techniques you see in the Windows API, you'll be OK. If you're not in control of how to interact with the DLL, then so be it. But if you can make the DLL's external interface more C-like, that would be best. And that doesn't mean you need to abandon the C++-style interface; you could provide two interfaces, where the C-style interface serves as a wrapper for your already-working C++style interface.
You can't pass a Delphi object to C++, at least not without a very good understanding of how the object model works at the binary level. If you need callbacks, do them using C types only and plain functions and procedures (no methods) and you should be fine.