I've googled quite a bit, and found it weird that no one cared to explain why COM interfaces are immutable. I suppose that the reason you're unable to remove any methods from a COM interface, is because a client relying on that interface, would encounter an error, which isn't good. But why would adding new features to the interface change any of that? Has this something to do with the underlying vtable?
COM has a very strong DLL Hell problem. Several basic reasons:
The programmers involved with writing the server and the client code rarely know each other, don't work together and have their own release schedules.
Registering servers is by default machine-wide, affecting every single client program that depends on the server. Isolated COM with a reg-free manifest is a workaround.
Early-bound COM (using a v-table) is very efficient but extremely intolerant to v-table changes. Mismatches are very hard to diagnose when the client code simply calls the completely wrong function or passes the wrong arguments. Late-bound calls through IDispatch is a workaround but slow.
COM programmers are very strongly motivated to cheat, changing the interface {guids} causes pretty grumpy client programmers and awkward support calls. Making an interface backwards compatible is relatively easy to do, making it forward compatible never works. Only changing the interface guid is truly safe.
Deployment of COM servers is often a client duty, they typically don't know enough about the server to troubleshoot and correct problems.
These are otherwise generic versioning problems, many runtime implementations suffer from them with various amounts of pain. A specific advantage in COM is that you can do something about it. Change the {guids} and a lot of the nastiness evaporates.
If you add a method, a newer client that uses that method will fail when working with an older version of the component.
Older versions of the component won't have the new method unless you specifically add code to implement it, rebuild the component, and then reinstall the component on all machines that use the component.
If a newer version of the client attempts to call the new method on an older version of the component that doesn't have the method, undefined behavior will occur (likely a crash but silent data corruption is also possible). The new client will be attempting to call a method through a pointer entry in the vtable that did not exist when the old client was built so the old client will have some unrelated value in this location.
Of course, this wouldn't be an issue for you if you control both client and component and deploy them together but COM is designed for a much broader range of use cases than that.
Related
Can I use the WRL library in C++ as a replacement for ATL to write a COM component? And if yes, would I be able to use it on older desktop Windows systems, like Windows XP?
I'm pretty sure that the answer to the first question is positive as I found this tutorial on MSDN:
http://msdn.microsoft.com/en-us/library/jj822931.aspx
but what about non-Windows 8 systems?
Well, sure you can. You can write a COM server in pure C++ code without any helper classes at all. You can write one in C if you really want to, although that's a violation of the Geneva Convention on Programmer's Rights in most jurisdictions.
What is probably not so visible is what is missing. WRL just doesn't make it any easier to write a server. Or maintain it. What you'll miss out on:
No help whatsoever to implement IDispatch. Obsoleted in WinRT but still quite important in regular servers. The only way to consume the server from a scripting language, IDispatch provides the late binding support.
No help whatsoever for registration. Obsoleted in WinRT, required for regular servers. Note how the DllRegisterServer() entrypoint is missing. The page you linked patches around the problem by requiring you to write a registry script by hand. That works, it is not exactly something you'd want to maintain or document so IT staff can get it right.
No wrappers for Automation types like BSTR, VARIANT and SAFEARRAY. Obsoleted in WinRT along with IDispatch. You can still fall back to <comutil.h> however.
No help whatsoever from the wizards that are built into Visual Studio that help you get it right. COM servers are awkward because definitions appear in multiple places in your code. And need to be an exact match. You get no help to ensure that CalculatorComponent is an exact match with the IDL, it is entirely up to you. Compiler errors you get from making small mistakes, particularly when maintaining it, can be painful.
And a whole bunch if smaller stuff not worth mentioning, like apartments, ActiveX, aggregation, error info, etc. Hurts pretty bad when you need it though. A possible advantage of WRL is that there's less mystical glue, ATL has a fair amount of it that considerably raises the abstraction level. That was intentional but it has to be learned. There's none at all when you use pure C++ of course, albeit that you have to write too much of it yourself.
Yes. You can write a standard COM component.
There is a sample for this directly in the docs.
And no: Such a COM component will only run on Windows 8 and later...
I don't really understand how ObjC can efficiently rely on messages. Does this mean a kernel such as mach has to be designed with this idea ?
Objective C seems like a good language, but I can't find it easier to grasp than C++.
How is a message system built in a language an advantage ?
The messaging in the Objective-C is not directly related to the messaging in the mach kernel. It's implemented as a highly-tuned function called objc_msgSend. The call
[obj messageWithX:x andY:y];
is translated to the C call
objc_msgSend(obj,#selector(messageWithX:andY:),x,y);
objc_msgSend is written directly in assembly language to be maximally optimized. It resolves the method call dynamically in a very efficient way. This blog post would be a good place to start understanding how it is implemented.
Whether it's easier or harder to grasp than C++ will depend on your background and your taste. The flavors of object-orientedness supported by C++ and Objective-C are quite different, and so it's difficult to compare.
Objective-C's messaging system is highly dynamic, and most of the decision can be done at the run time. C++'s member function invocation system is more static, and tries to do as much as possible at the compile time.
One merit of the dynamical nature of Objective-C is that you can change the class system at run time, but that's not necessarily related to the messaging nature. For example, the messaging system in mach doesn't do that, as far as I understand.
One feature directly related to the messaging nature is that an object can capture a message which it does not understand, and then forward it to other objects. This can be done in mach: the receiver of a message can either be in the kernel space, in the user space, or even in another machine, and the sender of the message doesn't need to care about it. This adds more flexibility in designing the kernel. (But this feature is not used in the mach kernel in OS X.)
Objective-C messaging is not built into the kernel, it is build into the Objective-C run-time.
Most of the magic is done in a function called objc_msgSend(). If you write a Objective-C code like this:
[myObject doStuffWith:something];
The compiler will actually generate the same code as if you had typed this:
objc_msgSend(myObject, #selector(doStuffWith:), something);
The implementation of of objc_msgSend() is quite fast and smart. Fast by caching frequently used selector, and smart in that it allows for implementation resolution as late as possible. What objc_msgSend() in practice do is a hash lookup for the selector to find an actual implementation.
One advantage that you have here is that if an implementation for a method is not found, then the object can at run-time either:
Defer the call to another object in order to act as a proxy.
Dynamically act on the selector.
Dynamically bind an implementation to the previously unknown selector.
The most obvios advantage of a dynamically typed language with messages is what you see in delegates. As you might have noticed in for example the UITableViewDelegate protocol; not all methods are declared as required.
This allows clients conforming to (implementing) a protocol to infer the default behavior simply by not implementing the delegate method at all. Whereas in for example Java it is quite common to apart from an interface Foo also have an abstract default implementation FooAdapter that implements default implementations for each and every method in the interface.
I've been given some Symbian C++ code to port over for use with the Android NDK.
The code has lots of Symbian specific code in it and I have very little experience of C++ so its not going very well.
The main thing that is slowing me down is trying to figure out the alternatives to use in normal C++ for the Symbian specific code.
At the minute the compiler is throwing out all sorts of errors for unrecognised types.
From my recent research these are the types that I believe are Symbian specific:
TInt, TBool, TDesc8, RSocket, TInetAddress, TBuf, HBufc,
RPointerArray
Changing TInt and TBool to int and bool respectively works in the compiler but I am unsure what to use for the other types?
Can anyone help me out with them? Especially TDesc, TBuf, HBuf and RPointerArray.
Also Symbian has a two phase contructor using
NewL
and
NewLc
But would changing this to a normal C++ constructor be ok?
Finally Symbian uses the clean up stack to help eliminate memory leaks I believe, would removing the clean up stack code be acceptable, I presume it should be replaced with try/catch statements?
I'm not sure whether you're still interested, but one possibility is that where the Symbian idioms are using the EUSER.DLL (i.e. TDesC derived classes, RPointer*, etc) you may find taking the open source EPL code from Symbian developer site and adding it directly into your port a viable option. That is port over the necessary bits of EUSER (and others perhaps?).
However, if your current code base already uses a lot of the other subsystems you're going to see this become very unwieldy.
You should try to read some introductory text on development for Symbian. They used to have some examples in the Symbian site, and I am sure that you can find specific docs on how the types you want are meant to be used and what they provide.
The problem is that symbian development has its own idioms that cannot/should not be directly used outside of the symbian environment, as for example the two phase construction with the cleanup stack is unneeded in environments where the compiler has proper exception handling mechanisms --in Symbian a constructor that throws can lead to all sorts of mayhem.
If this is not a very large codebase it may be easier/faster to start from scratch and doing everything Android style. Even if you require NDK/C++ this approach may be quicker.
Another approach may be to use portable C/C++ for the core, and the use this on both Symbian and Android version while doing UI stuff separately for each platform. Spotify have done this on Android and iPhone.
It would typically be a bad idea to try and port Symbian OS C++ to standard C++ without having a very good understanding of what the Symbian idioms do.
This could very well be one of these projects where the right thing to do is to rewrite most of the code pretty much from scratch. If you barely know the language you are targetting, there is little point in deluding yourself into thinking you won't make mistakes, waste time and throw away new code anyway. It's all part of learning.
The CleanupStack mechanism is meant to help you deal with anything that could go wrong, including power outage and out of memory conditions. Technically, these days, it is implemented as C++ exceptions but it covers more than the usual error cases standard C++ code normally handles.
Descriptors (TDesc, TBuf and HBuf all belong to the descriptor class hierarchy) and templates (arrays, queues, lists...) predate their equivalent in standard C++ while dealing with issues like the CleanupStack, coding standards, memory management and integrity...
A relevant plug if you want to learn about it: Quick Recipes On Symbian OS is a recent attempt at explaning it all in as few pages as possible.
You should also definitely look at the Foundation website to get started.
Classes prefixed by T are meant to be small enough by themselves that they can be allocated on the stack.
Descriptor classes suffixed by C are meant to be immutable (A mutable descriptor can usually be created from them, though).
HBufC is pretty much the only Symbian class prefixed by H. It should always be allocated on the Heap.
A method suffixed by C will add an object on the CleanupStack when it returns successfully (usually, it's the object it returns). It's up to the calling code to Pop that object.
Classes prefixed by R are meant to be allocated on the stack but manage their own heap-based resources. They usually have some kind of Close() method that needs to be called before their destructor.
A typical way to thing about the differences between a collection of objects and a collection of pointers to object is who owns the objects in the collection. Either the collection owns the objects when they are added and looses them when they are removed (and is therefore responsible for deleting each object it still contains when it is itself destroyed) or the collection doesn't transfer ownership and something else must ensure the objects it contains will stay valid during the collection's lifetime.
Another way to think about collections is about how much copying of objects you want to happen when you add/get objects to/from the collection.
Symbian descriptor and collection classes are meant to cover all these different ways of using memory and let you choose the one you need based on what you want to do.
It's certainly not easy to do it right but that's how this operating system works.
Assume that you work only in the C++ world (cross-language interop is not required). What advantages/inconvenients do you see in using COM instead of a plain basic DLL? Do you think using COM is worth the trouble if you are not going to use the interface from different languages?
Everybody is mentioning things that are in COM's plus column. I'll mention a couple of detractions.
When you implement your system using COM, you need to register the COM 'servers' (be they in-proc or out-of-proc) at setup and unregister them at uninstall. This could increase the complexity of your setup system slightly and tends to require a reboot unless the user carefully tears down running processes first.
COM is slow compared to other standard ways of doing the same thing. This comment will probably generate a lot of hate and maybe some downvotes, but the fact of the matter is that at some point you will need to marshall data, and that is expensive.
According to the Rules of COM, once an interface has been published it can never be changed. That in itself is not a negative, and you might even argue that it forces you to do thorough design before shipping the interface. But the truth is there's no such thing as never, and in production code interfaces change. You will undoubtedly need to either add methods or change the signatures of existing methods. In order to accomplish this you have to either break the rules of COM -- which has bad effects -- or follow the rules of COM which are more complicated than just adding a parameter to a function like you would with a astraight DLL.
COM can be useful in plain old C++ for:
Interprocess communication
Plugin architectures
Late binding scenarios
"Much, much, more..." (tm)
That said, if you don't need it, don't use it.
With DLL you can get much closer coupling, while COM limits interactions very precisely. This is the root of both the advantages and the disadvantages!
You get more power and flexibility (e.g. inherit from classes defined in the DLL, not feasible in COM) but the dependency is thereby much stronger (need to rebuild the user for certain changes to the DLL, etc).
Often especially galling is that all DLLs and the EXE must use the same kind of runtime library and options (e.g. all dynamically linked to the non-debug multithreaded version of msvcrt* for example -- can't rebuild just one to use the debug version without incurring very likely errors!).
The looser coupling of COM is therefore often preferable, unless you really need the closer-coupling kinds of interactions in a specific case (e.g., a framework, which definitely requires user-code to inherit from its classes, should be a DLL).
If you can avoid don't use it. In my last project COM brought pretty much limitations into C++ interfaces being used. Just imagine, that you can't simply pass a std::string but have to use an array of characters. In that case you build the string, an then copy it to an array which can be handled by COM.
You also can only use very limited set of fundamental types, have casts and proprietary memory management. You can't use new/delete, but have to use COM own functions.
You also can't simply throw an exception, but have to initialize some COM interface IErrorInfo, which will be rethrown at the other end.
So if you don't need, don't use it. It will definitely screw your design. And if you need it, try to evaluate other interop possibilities: boost::interprocess, zeroc ice...
Regards,
Ovanes
Registration and discovery
Out-of-process
Remote invocation
are the few extra features that you would have got. Even transactional support can flow without the need for COM support these days.
The IUnknown interface is a good base level to support anyway -- gets you a way to add features without breaking old clients (QueryInterface) and pervasive reference counting. You can implement this without buying into everything in COM.
Then, whenever you are adding a feature to a class, if you use the COM interface for it, you at least get an interface that is known -- for example IDispatch if you want reflection features.
Your only delta away from being able to be called by another language would then be the registration and the class factory.
Because interfaces are independent of any particular DLL, at its simplest level, a COM like approach at the very least frees you to change the dll serving an interface under the hood, without having to recompile your app against the new dll name.
Using Full COM with MIDL defined interfaces and proxy stub dlls means that you can use COM to manage thread safety in-process, interprocess comms on the same PC, or even connect to the COM server object on a remote PC.
I have a data acquisition program written in C++ (Visual Studio 6.0). Some clients would like to control the software from their own custom software or LabView. I would like to come up with a simple API with a dll I can distribute to them and would like some tips on how to get started. This is going to be VERY basic, maybe 4 or 5 commands. My DAQ program will still be running in its own window on the same machine, I would just like to set it up to be controlled from another program.
You are on the right track with a DLL. The real trick, it sounds like, will be deciding what sort of inter-process communication (IPC) you want to use. Options are: sockets, pipes, shared memory, synchronization objects (events, etc.), files, registry, etc.
Once you decide that, then implement a listener within your executable to wait for incoming IPC messages from whatever software is using your DLL.
As far as the API is concerned, you can keep it simple just like you were wanting. Have the DLL expose your 4 or 5 functions (make sure you only use native data types, like char* and long, to avoid module boundary issues), and then those will use your IPC mechanism to communicate with your executing app.
Things that start simple like this have a habit of growing over time, so you may be better off doing a little more work up front and using a technique that will grow with you.
Implementing a COM interface to your program would give the clients are lot of freedom in how the interface with it, and you wouldn't have to worry about the mechanics of IPC, etc since COM is designed to hide all that from you.
In the future COM already has well define idioms for things like events that are well support by scripting languages, etc should you need them.
Update: there are a lot of ways of implementing COM. You can build it from the first principals with the guide of a good COM book, or use of framework like ATL to save some of the boiler plate. There are a lot of good samples, for example see MSDN.
The big advantage of COM is that you don't need a DLL! Your application would always be running, you say. That means that it can act as the COM object creator ("local server").
If someone would want a "stdcall" DLL instead, you could give them a DLL that internally just forwards all calls to the COM interface. Writing it would be quite trivial. You only have 5 functions, you say. That suggests you have one COM interface, with those 5 methods. When the wrapper DLL loads, it asks your EXE to create its COM object. The DLL in turn exposes 5 stdcall methods, each of which calls one method on the COM object.
You could use a dll. I'd consider it. But I'd also consider whipping up a simple http-based API, preferably RESTful.
Advantages: Easy to port. Can write a client app from any language trivially. Can work across a network. Testing becomes easier (use a scripting language or your browser).
Disadvantages: Performance is going to be slower. Significantly more plumbing to set it up in C++. I'm not sure if LabView can make http calls.
Something like:
http://xxx/data [GET, maybe POST for testing]
http://xxx/data/start [POST]
http://xxx/data/stop [POST]
http://xxx/data/parameters [POST]
Given your requirements it may be slightly overkill but then maybe not. Many apps I've worked on have had to be ported and would have been quicker to extend if we could have used a faster dev language to test and extend it.
LabVIEW supports making DLL calls, but this is one of the weaker spots in LabVIEW development. Done incorrectly, this can lead to an application that is more prone to crashes. As a LabVIEW developer, I like MattyT's suggestion of creating an HTTP service. Every language on every platform that can make a TCP/IP port can access it then. I think you could use your own custom TCP/IP protocol instead of full bore HTTP, but either way the compatability issue is solved.
If you do use DLLs, here are some tips. Don't use structs or pointers to structs in your function call argument list. Don't allocate memory in the DLL to be passed back to LabVIEW. LabVIEW has built in memmory management and won't play well with others. This may apply to other languages that have memory management such as Java. LabVIEW will work better if it allocates the memory and passes a pointer to the DLL. Avoid pointers, arrays and strings where possible. LabVIEW can pass these to DLLs, but it is an advanced topic and works best when the LabVIEW developer also knows C, which will not always be the case.
There is a related question here. I don't want to end up with something that is LabView-specific, and it appears that LabView can access dlls if they use stdcall. A dll like this would be callable from a VB or other Windows software as well which is what I'm shooting for.
I'm not sure about it's ability to access a COM interface but would appreciate some more detail on what that would look like for my application.