I'd like to make dynamic (i.e. reflection-based) calls to WinRT objects, from C or C++. I will assume that I have winmd files available at run-time, so that I can find out what the methods are and what parameters they take.
In OLE Automation, IDispatch was then available to make the actual calls. However, WinRT objects don't support IDispatch. How can I then make calls? Do I need some kind of FFI library that will allow to dynamically pass the parameters, according to the COM calling convention of the processor? Or do I really need "static" class/struct declarations (for C/C++)?
Edit: The target system is a metro-style app. That precludes solutions involving banned APIs.
It is certainly possible to build what you're describing - under the covers that's exactly what the Chakra Javascript engine does with winrt metadata and is similar to what the CLR does. Both of these language projections discover the APIs at runtime and build up the low level assembly to make this happen.
It's a lot of work and isn't particularly pleasant but it's absolutely technically possible. The windows metadata contains all the information needed to create stubs for the APIs and structures.
Related
I would like to understand the purposes of the files mentioned in this article and link the knowledge to my current COM server and COM client scenario, so that I can implement my COM server to use the COM server: this
I am having a COM server which is an exe, or service, that runs in the background. For now, I know there is an exposed interface inherited both from IUnknown and IDispatch. Besides I have the following files generated:
xxx_i.c defines all the CLSIDs and IIDs
xxx_i.h defines all the method the interface supports
xxx_p.c ?
dlldata.c ?
I am now using the automation way, IDispatch -> Invoke(), to access the interface methods. Although this way seems work fine without using any files mentioned above, I still would like to understand the purposes of them while using the normal way, IUnknown -> QueryInterface(), to access the methods.
Since I am new to the COM world, any suggested reading would be appreciated! Thanks!
In its most simple form, COM is only the vtable binary contract plus the mother of all interfaces: IUnknown. COM is a way to reuse code without source, with components, it's some kind of a dynamic casting mechanism. Provided I know the coclasses you support (their CLSID), the interfaces they expose (their IID), and what are these interfaces' methods layout, their parameters, order, type, etc., I can use your COM server.
But to ease "communication" between your COM clients and your COM server, you can/should use some standard mechanisms/documentation and add tooling so plumbing stuff like marshaling (=serialization) will be taken care w/o any effort. This is crucial in the out-of-process case, less important with in-process (I will elude the "apartment" concept here...)
So, lots of things you'll find in COM (like registration, tooling, IDL, typelibs, etc.) are in fact optional, but also very useful (so they kinda become mandatory in the end). The purpose of things like idl (for "interface language definition") is to define and expose to your COM clients what your COM server supports so tooling can generate a lot of code automatically for you and your clients (.c, .h, .tlb). Note that nothing prevents you from implementing interfaces or coclasses without defining them in idl. Nothing obliges you to provide your .idl or your .tlb. In this case, I will only be able to use them if I known their IID, method layout etc.
Then, on top of IUnknown, Microsoft created a universal interface called IDispatch (this is also known as "Automation", or "Late binding" as opposed to "Early binding" for IUnknown), at that time targeting VB/VBA clients (before even VBScript, JScript, and lots of other COM clients, .NET supports IUnknown and IDispatch). IDispatch, if you go that route, could be the last interface you'll ever have to implement, because its semantics allows full discovery and invocation of any method, provided it supports a finite set of defined data types, the "Automation types": BSTR, VARIANT, etc.
So, if you support IDispatch, provide a TLB (typelibs) and restrict all types to Automation types, then you don't need to handle marshaling, you don't need proxies and stubs, you can forget about all this, even in out-of-process scenarios, because Microsoft implements that automatically. Back in the days, we used to call "oleaut32.dll" the "universal marshaler".
Dual interfaces are interfaces that support both IUnknown and derivates and IDispatch at the same time. They mostly exist to support C/C++ clients and Automation clients at the same time. Using Automation (BSTR, VARIANT, etc.) is a bit painful in C/C++ because they were not intended originally to be used by C/C++ clients... Note Microsoft proposes C++ smart wrappers classes: CComBSTR and CComVARIANT with ATL, or _variant_t and _bstr_t with the Windows SDK.
Requests for reading material are out of scope for StackOverflow, but I can't help but to reccomend the seminal work by Don Box: Essential COM which is in print and available as an ebook elsewhere. Here's Don's description of the topic:
Box, Don. Essential COM. Addison-Wesley, 1998, pp. 350:
COM is based on client programs having a priori knowledge of an
interface's definition at development time. This is accomplished
either through C++ header files (for C++ clients) or through type
libraries (for Java and Visual Basic clients). In general, this is not
a problem, as programs written in these languages typically go through
some sort of compilation phase prior to being deployed. Some languages
do not go through such a compilation phase at development time and
instead are deployed in source code form to be interpreted at runtime.
Perhaps the most pervasive of such languages are HTML based scripting
languages (e.g., Visual Basic Script, JavaScript) that execute in the
context of either a Web browser or a Web server. In both of these
cases, script text is stored in its raw form embedded in an HTML file,
and the surrounding runtime executes the script text on the fly as the
HTML is parsed. To provide a rich programming environment, these
environments allow scripts to invoke methods on COM objects that may
be created in the script text itself or perhaps elsewhere in the HTML
stream (e.g., a control that is also part of the Web page). In these
environments, it is currently impossible to use type libraries or
other a priori means to provide the runtime engine with a description
of the interfaces being used. This means that the objects themselves
must assist the interpreter in translating the raw script text into
meaningful method invocations.
To allow objects to be used from
interpretive environments such as Visual Basic Script and JavaScript,
COM defines an interface that expresses the functionality of
interpretation.
Tl;dr: there are two ways to do everything in COM (ignoring IInspectable and dual interfaces):
IUnknownStandard virtual method invocation. Fast, no extra code. Requires compile time interface information (.h or .tlb) on the client calls
IDispatch"Late Binding". Slow, lots of interpreting code. No client compilation or interface spec needed.
Practically speaking, unless you are calling from VBA, VBScript or have some old VB6 clients then you are better off sticking with IUnknown exclusively.
..for an out-of-process-server, or can I call a dispatch interface without registering a proxy/stub?
The interface in question is very high level, so performance is a non-issue, and I could make the whole thing registration-free, which is a big plus
I'm pretty sure you don't need to provide a custom proxy/stub dll if you limit your interface(s) to automation-compatible types. In that case, the system can use the automation marshaler and doesn't need any additional help. I believe the automation-compatible types are the types that can fit into a VARIANT, e.g. simple POD types, BSTRs, and the like.
I found this KB article which has some discussion of the automation marshaler, although it's not specifically targeted at your question. It does list the compatible types, at the very least. It also mentions that you need to specifically identify the automation marshaler in the registration for your component, but in my experience this isn't necessary - your mileage may vary.
Lastly, you may need to implement IProvideClassInfo as well; I usually use the implementation provided by ATL.
You only need a proxy/stub dll if your interface needs to be marshalled. This means if your COM server is in process, and the interface is not passed between apartments, and you aren't going to be calling it from .Net or any other situation that would require it to be marshalled, then you do not need a proxy/stub dll.
Our industry is in high-performance distributed parallel computing. We have an unmanaged C++ application being developed using Visual Studio 2008.
Our application (more like a framework) is supposed to be able to dynamically load code (algorithms) developed by 3rd parties (there can be many dlls) that conforms to our interface specification, and calls the loaded code to get some results.
Think of it like you want to call a sin(x) function, but there are many different implementations of sin(x) that you could use.
I have a few questions as I'm very new to this area of dynamically loading code:
Is dll (dynamic-link library) the answer to this type of requirement?
If the 3rd-party used a different type of IDE to create the dll compared to mine (say Eclipse CDT, C++Builder, Visual C++ 6.0, etc), would the dll still work with my application?
Our application is supposed to work cross-platform as well (should be able to run on Linux), would using QLibrary be the most logical way to abstract away all the platform-specific dll loading?
(OPTIONAL) Are there some unforeseen problems that I might encounter?
1) generally, yes. If the API gets complex and multi-object, I'd use COM or a similar mechanism. But if you have to manage only a little state, or can go completely state-free, a pure DLL interface is fine.
2) Use a suitable calling convention (stdcall) and data types. I would not even asusme that the implementation has to be in C++. so that means char/wchar_t, explicit-sized ints, e.g. int32 , float and double, and C-style arrays of them.
3) can't say
4)
No cross-boundary memory allocations: free what you allocate, and let the plugin free what it allocated.
Your API design has a big influence on achievable performance and implementation effort. DOn't make the functions to small, give the implementation some freedom how it handles certain things, define error protocol, threading requirements etc.
[edit]
Also, if you declare structures, look into alignment and compiler options to control this (usually #pragma pack). This is required so clients see the same layout.
The compiler usually "mangles" the names for the exported symbols (e.g. add an udnerscore for STDCALL convention). Typically, this is controlled through a .def file that is passed to the linker.
Yes, it is. But there are many issues.
May or may not. Firstly, you should be aware of calling conventions. Secondly, since there is no standardized ABI for C++, you should stick to plain C at interface level (Btw, COM technology was all about this -- making a standardized ABI). Thirdly, each plugin may have its own CRT and so problems may appear, there is a good article about this on MSDN.
Yes, this will help with loading dynamic libraries, but not with problems in (2). Althought, these problems mostly windows specific.
In my experience, QLibrary is the best answer to your questions.
It provides a simple interface and takes care of all the platform-specific details.
Indeed, that means that the plugins must be also written using QT.
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 need to build a C++ library to distribute among our customers. The library must be able to be accessed from a wide range of languages including VB6, C++, VB.net and C#.
I've being using ActiveX controls (ocx files) until now. But I wonder if there is a better kind of library (dll, etc.) that I can build. What do you recommend?
I'm limited to C++ as the library language, but you can mention other languages for reference to other developers.
P.S. Sorry if the question was already asked. I had some trouble finding a suitable title. Feel free to correct my English.
Edit: Seems like the best choice is either DLLs or OCX (i.e., COM), but I'm still having some doubts on which one will I choose. Which one is more suitable to modern languages (.NET for instance)? Which one would be easier to use from an end developer perspective?
Almost every language has a way of loading dynamic libraries and accessing exported C functions from them.
There is nothing preventing you from using C++ inside the dll but for maximum portability, export only C functions.
I have some more about this in this post.
If you're looking at supporting both VB6 and .NET, you're pretty much stuck with exposing interfaces via COM, but at least that'll get you out of having to create more than one wrapper based on the language/runtime system you're trying to interact with.
If there is any chance this will need to be ported to non windows platforms then a DLL / Shared library is your best choice as a COM object really isn't at all portable.
In addition you can call a DLL from almost any platform even if it requires you to write a wrapper of some kind. It's pretty easy to wrap a dll in a com object but if you make a native com object it's a lot harder to add a C style DLL API. Plus you might want to call it from java for example and it's much easier to write a JNI wrapper to call your DLL than get it working with COM in any kind of cross platform way.
Really it depends on what platforms you really need to call it from and how certain you can be that you won't get something out of the ordinary in future.
To be callable from all those languages your only real option is going to be COM, without having to write wrappers where required (which would defeat the point)