We're interfacing to some 3rd party COM objects from a C++Builder 2010 application.
Currently we import the type library and generate component wrappers, and then are able to make method calls and access properties in a fairly natural way.
object->myProperty = 42;
object->doSomething(666);
However, we've been bitten by changes to the COM object's interface (which is still being extended and developed) causing our own app to fail because some method GUIDs seem to get invalidated - even if the only change to the interface has been the addition of a new method).
Late Binding has been suggested as a way of addressing this. I think this requires our code to be changed rather like this:
object.OlePropertySet("myProperty", 42);
object.OlePrcedure("doSomething", 666);
Obviously this is painful to read and write, so we'd have to write wrapper classes instead.
Is there any way of getting late binding wrappers generated automatically when we import the type library? And, if so, are they smart enough to only do the textual binding once when the object is created, rather than on every single method call?
When you import a TypeLibrary for a COM object that supports late-binding (when it implements the IDispatch interface), the importer can generate separate wrapper classes (not components) for both static-binding and late-binding.
Adding a new method to an existing interface should not invalidate your code. Methods do not have GUIDs. However, for an IDispatch-based interface, its methods do have DISPID values associated with them, and those DISPID values can be changed from one release to another. Though any respectable COM developer should never do that once an interface definition has been locked in.
After deep investigation of the code and headers generated by the TLIBIMP, this turns out to be fairly easy.
If your Type Library has a class Foo, then after importing the type library, you would typically use the auto-generated smart pointer classes IFooPtr.
{
IFooPtr f;
...
f->myMethod(1,2);
}
You should note that at this point that the bindings are static - that is, they depend not just on the GUIDs of the objects and the DISPIDs of the methods, but on the exact layout of the VTable in the DLL. Any changes that affect the vtable - for instance, adding an additional method to a base class of Foo will cause the method call to fail.
To use dynamic bindings, you can use the IFooDisp classes instead of IFooPtr. Again, these are smart wrappers, handling object lifetimes automatically. Note that with these classes you should use the . operator to access methods, not the indirection -> operator. Using the indirection operator will call the method, but via a static binding.
{
IFooDisp f;
...
f.myMethod(1,2);
}
By using these IDispatch-based wrappers, methods will be dispatched by their DISPIDs, even if the objects vtable layout is changed. I think these classes also give a way to dispatch by function name rather than DISPID, but haven't confirmed the details of that.
Related
I have incomplete types from my COM type library .tlb (which was generated by regasm OF .NET v4+) I am unsure if this is because cppc.exe derived the wrong header for it or if this is merely a symptom of it.
I know it's incomplete because all the generated classes come out a. as structs and b. with empty interface bodies (no methods defined).
I'm sure I've done something wrong when making my .dll suitable for regasm; I've changed the Assembly-Info and I've made default constructors for-all types. Was I meant to do something else maybe?
If you mark your assembly as COM-visible, all public classes with a default constructor are exposed with the help of a dispinterface. This interface type is designed for late bound clients, such as scripting languages, which invoke methods and properties via Dispatch identifiers (DISPIDs). An accompanying type library won't contain any entries for the interface.
In order to bind to a fixed layout, you’ll need to switch to a dual or IUnknown interface. Simply edit your AssemblyInfo.cs as follows:
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(true)]
[assembly: ClassInterface(ClassInterfaceType.AutoDual)]
Now, the methods of the interface are visible in the type library, as well as in IntelliSense.
Note however that with an AutoDual exposed class, you'll need to need to take care when updating the assembly. See this link for further info.
Coming from Delphi, I'm used to using class references (metaclasses) like this:
type
TClass = class of TForm;
var
x: TClass;
f: TForm;
begin
x := TForm;
f := x.Create();
f.ShowModal();
f.Free;
end;
Actually, every class X derived from TObject have a method called ClassType that returns a TClass that can be used to create instances of X.
Is there anything like that in C++?
Metaclasses do not exist in C++. Part of why is because metaclasses require virtual constructors and most-derived-to-base creation order, which are two things C++ does not have, but Delphi does.
However, in C++Builder specifically, there is limited support for Delphi metaclasses. The C++ compiler has a __classid() and __typeinfo() extension for retrieving a Delphi-compatible TMetaClass* pointer for any class derived from TObject. That pointer can be passed as-is to Delphi code (you can use Delphi .pas files in a C++Builder project).
The TApplication::CreateForm() method is implemented in Delphi and has a TMetaClass* parameter in C++ (despite its name, it can actually instantiate any class that derives from TComponent, if you do not mind the TApplication object being assigned as the Owner), for example:
TForm *f;
Application->CreateForm(__classid(TForm), &f);
f->ShowModal();
delete f;
Or you can write your own custom Delphi code if you need more control over the constructor call:
unit CreateAFormUnit;
interface
uses
Classes, Forms;
function CreateAForm(AClass: TFormClass; AOwner: TComponent): TForm;
implementation
function CreateAForm(AClass: TFormClass; AOwner: TComponent): TForm;
begin
Result := AClass.Create(AOwner);
end;
end.
#include "CreateAFormUnit.hpp"
TForm *f = CreateAForm(__classid(TForm), SomeOwner);
f->ShowModal();
delete f;
Apparently modern Delphi supports metaclasses in much the same way as original Smalltalk.
There is nothing like that in C++.
One main problem with emulating that feature in C++, having run-time dynamic assignment of values that represent type, and being able to create instances from such values, is that in C++ it's necessary to statically know the constructors of a type in order to instantiate.
Probably you can achieve much of the same high-level goal by using C++ static polymorphism, which includes function overloading and the template mechanism, instead of extreme runtime polymorphism with metaclasses.
However, one way to emulate the effect with C++, is to use cloneable exemplar-objects, and/or almost the same idea, polymorphic object factory objects. The former is quite unusual, the latter can be encountered now and then (mostly the difference is where the parameterization occurs: with the examplar-object it's that object's state, while with the object factory it's arguments to the creation function). Personally I would stay away from that, because C++ is designed for static typing, and this idea is about cajoling C++ into emulating a language with very different characteristics and programming style etc.
Type information does not exist at runtime with C++. (Except when enabling RTTI but it is still different than what you need)
A common idiom is to create a virtual clone() method that obviously clones the object which is usually in some prototypical state. It is similar to a constructor, but the concrete type is resolved at runtime.
class Object
{
public:
virtual Object* clone() const = 0;
};
If you don't mind spending some time examining foreign sources, you can take a look at how a project does it: https://github.com/rheit/zdoom/blob/master/src/dobjtype.h (note: this is a quite big and evolving source port of Doom, so be advised even just reading will take quite some time). Look at PClass and related types. I don't know what is done here exactly, but from my limited knowledge they construct a structure with necessary metatable for each class and use some preprocessor magic in form of defines for readability (or something else). Their approach allows seamlessly create usual C++ classes, but adds support for PClass::FindClass("SomeClass") to get the class reference and use that as needed, for example to create an instance of the class. It also can check inheritance, create new classes on the fly and replace classes by others, i. e. you can replace CDoesntWorksUnderWinXP by CWorksEverywhere (as an example, they use it differently of course). I had a quick research back then, their approach isn't exceptional, it was explained on some sites but since I had only so much interest I don't remember details.
I have a little trouble in understanding a wrapper class. It would be great if some one could help providing apt examples.
What is a C++ Wrapper Class and what are the circumstances of writing it ?
What is it's use any way ?
Thanks.
A "wrapper class" is a de facto term meaning a class that "wraps around" a resource; i.e, that manages the resource. When people write a wrapper, then, they are doing something like this:
class int_ptr_wrapper
{
public:
int_ptr_wrapper(int value = 0) :
mInt(new int(value))
{}
// note! needs copy-constructor and copy-assignment operator!
~int_ptr_wrapper()
{
delete mInt;
}
private:
int* mInt;
};
This class manages ("wraps") a pointer to an int. All resources should be wrapped in some fashion, for cleanliness (no explicit clean up code or noise) and correctness (destructor is guaranteed to run; cannot forget to clean up, and safe with exceptions).
This pattern is called Scoped-bound Resource Management (SBRM), though a far more common (but most esoteric) name is Resource-Acquisition is Initialization (RAII). The idea is to bind a resource's clean-up to a destructor, for the reasons given above: the scope handles the rest.
Note that I said it was missing a copy-constructor and copy-assignment operator. This is due to the Rule of Three. (See linked question for detailed explanation.) The simplest way to correctly implement this rule is with the copy-and-swap idiom, explained here.
Sometimes, it's not pragmatic to write wrapper class for resource clean-up, usually when the resource is unique or used once. (Or with transactional programming.) The solution to this is called scope guard, a way of writing clean-up code inside the function that needs it.
You may find more information by searching for it in your favorite search provider (that is, Google), or going to the "primary" document here. Note that Boost provides a utility for this, as it usually does for good idioms.
A wrapper is just some smallish class whose purpose is to provide a different interface than the thing it wraps. For example, it is common to take a C API and write one or more classes that "wrap" it to provide an object-oriented interface rather than a procedural one.
You asked for circumstances of writing wrapper classes.For example, if you are in a company that makes use of different types of cameras, let us say USB, firewire etc. Each of the manufacturers will provide a different set of functions through an API to start the camera, set the parameters and read the image stream from it.
Now the programmer who builds the applications in your company need to be insulated from all the specific details in the various APIs. Now, what you can do is write a wrapper class around the APIs for each of the cameras or smarter, just one class with simple functions, wrapping around the existing code provided by the API.
For instance, we can design classes
MyUSBCameraWrapperClass,
MyFirewireCameraWrapperClass
with some member functions like
setFrameRate(int fps),
getImgFrame(*framebuffer), etc.
The programmers in your company can then use MyUSBCameraWrapperClass usbcam; usbcam.setFrameRate(30), etc. You get the point??
A wrapper class is a class that wraps a functionality with another interface.
Suppose you have the function f():
void f() { std::cout << "hello\n"; }
A simple wrapper class might be
class C {
f() { std::cout << "hello\n"; }
};
You might write a wrapper when your existing codebase expects a particular interface. This is the essence of the adapter design pattern. Or you might wrap a function in a class if you wish to maintain state for that function. Or you might wrap a function in a class' constructor or destructor if you want it to conveniently and automatically be called for you in a correct and deterministic manner. And the list goes on.
I use two kinds:
resource wrappers for function pairs provided by the OS like
UNIXs: open/close, mmap/munmap, dlopen/dlclose
Windows: CreateFile/DestroyHandle, CreateFileMapping/CloseHandle, LoadLibrary/FreeLibrary
functional wrappers for functions provided by the OS like
UNIXs: write, read, dlsym
Windows: ReadFile, WriteFile, GetProcAddress
The resource wrapper makes certain, that compiler generated code worries about the destruction of the resource created by the constructor via what is today called RAII. It is easy to combine such classes via base/member class relationships into complex classes.
In case of the creation function fails, a system error exception is thrown, providing rich error information about the error.
The functional wrapper is used instead of the plain OS function. Also in case of failure a system exception is being thrown.
This way somebody using my code doesn't need a debugger and debug code to find out what is failing in a complex environment with many libraries and processes and remote machines.
Also these wrappers provide some OS abstraction -- the code using them does not have to worry about OS differences.
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.