Using Component Object Model (COM) on non-Microsoft platforms - c++

I'm regularly running into similar situations :
I have a bunch of COM .DLLs (no IDL files) which I need to use and invoke to be able to access some foreign (non-open, non-documented) data format.
Microsoft's Visual Studio platform has very nice capabilities to import such COM DLLs and use them in my project (Visual C++'s #import directive, or picking and adding them using Visual Basic .NET's dialogs) - and that's the vendors recommended way to use them.
I would be interested into finding a way to use those DLLs on non-microsoft development platforms. Namely, using these COM classes in C++ project compiled with MinGW or Cygwin, or even Wine's GCC port to linux (compiles C++ targeting Win32 into binary running natively on Linux).
I have got some limited success using this driver, but this isn't successful in 100% of situations (I can't use COM objects returned by some methods).
Has someone had success in similar situations ?

Answering myself but I managed to find the perfect library for OLE/COM calling in non-Microsoft compilers : disphelper.
(it's available from sourceforge.net under a permissive BSD license).
It works both in C and C++ (and thus any other language with C bindings as well). It uses a printf/scanf-like format string syntax.
(You pass whatever you want as long as you specify it in the format string, unlike XYDispDriver which requires the arguments to exactly match whatever is specified in the type library).
I modified it a little bit to get it also compile under Linux with WineGCC (to produce native Linux elf out of Win32 code), and to handle "by ref" calls automatically (stock disthelper requires the programmer to setup his/her own VARIANT).
My patched version and patches are available as a fork on github:
https://github.com/DrYak/disphelper
And here are my patches :
patch for single source
patch for split source

The problem with the Ole/Com Object Viewer packaged with Visual Studio and Windows SDKs is that it produces a broken .IDL out of the .DLL, which can't further be compiled by MIDL into a .H/.CPP pair.
Wine's own reimplementation of OleViewer is currently unstable and crashes when trying to use those libraries.

I think you should be able to use the free tool Ole/Com Object Viewer to make the header files.

Related

Can C++Builders clang32 compiler consume VS libraries

I'm trying out the clang32 compiler coming with C++ builder 10.2. Builder don't yet have any good support for CMake, so a great number of 3rd party libraries are (very) hard to compile using it.
Anyone knowing if there is any binary compatibility between clang32 and Visual Studio compiler?
There are essentially three different levels of compatibility you need to worry about:
File formats for object code and debug data, which allow you to use clang to build part of your project and Visual C++ cl.exe to build a library and then link them together and debug both.
Ability to write code and structure data that conforms to a portable binary interface, so it can be called across a mix of compilers.
Binary compatibility of the C++ standard library, so that standard library objects can be shared across a mix of compilers.
I can definitely say that (2) is supported and (3) absolutely is not; you can't even share standard library objects between different patchlevels of the same compiler. For (1) I don't know. A common way to bypass the issues with (1) is to build a DLL using each compiler, so they dynamically interface but no static linking nor merging of debug data is necessary.
If your concern is about cmake though, I think your problem is not the compiler (clang is available for Linux and cmake supports it well -- you should find the make scripts are capable of configuring all the compiler options). Whether it can generate project files for C++Builder is a different story, but perhaps you should consider using a different IDE. There are many with clang support, even Microsoft's Visual Studio has some ability to use clang for the compile step, and it's getting better with each release.

How can a C++ dynamic library with a C++ interface not break ABI between different compiler versions?

Recently I have been using the Assimp library for my hobby 3D graphics engine project in order to load 3D models.
The library comes in the form of a DLL accompanied by an import library (LIB) and an EXP file (only when building from latest sources; I understand it holds information about the exported functions, similar to the LIB)
Now, the surprise part, which made me ask this question, is the following:
I was able to correctly, without any build/link errors or run-time errors use the C++ interface of two different versions of the library:
The pre-built library, release 3.1.1, which was built and is dependent on an older runtime (MSVCP110.DLL, MSVCR110.DLL) (which I later decided to change to my own build since there was a linking error in that binary build)
My own source build made with the VS 2013 compiler, depending on MSVCP120.DLL and VCRUNTIME120.DLL
I was able to use both of these library binaries with my executable binary, when built with either:
VS 2013 compiler
VS 2015 compiler
My surprise of the success of using the library like described above, without any error, is caused by:
reading all over the internet about how C++ libraries and interfaces are not binary compatible (ABI) between different compiler versions, and thus cannot be used together with binaries built with other compilers. Exceptions: usage through C interfaces, which maintain the ABI compatibility; COM libraries (COM interfaces were built to overcome the same issue).
Using binaries built with different compilers can raise problems because of function name mangling (may be solved by the import library?!), dynamic memory allocation and freeing done by different versions of the allocators/destructors.
Can anyone provide some insight on this use case, on why I successfully managed to use a VS 2013 built dynamic library together with a VS 2015 toolset application without any of the above described problems? Also, the same applies when using the pre-built binary both with a VS 2013 build and a VS 2015 build of my 3D engine application.
Is it an isolated case or does the Assimp library itself take care of the problems and is implemented in such a way to ensure compatibility?
The actual usage of the library was pretty straightforward: I used a local stack variable of an Importer object (class) and from there on manipulated and read information from a bunch of structs; no other classes (I think)
As long as all the classes and memory used in the DLL is allocated and freed and maintained inside the class, and you don't use standard library container objects across the interface boundary you are completely safe to do it.
Even the use of std:string isn't allowed across DLL boundaries if the modules use different compilers or even have a different CRT usage, or at least a different CRT.
In fact, using plain interfaces (pure virtual classes) is safe for all VS C++ compilers. Also using extern "C" is safe.
So if the structures you exchange are just PODs or have simple plain data objects, and as long as allocation and destruction is done all inside the DLL you are free to mix and use DLLs build with different compilers.
So the best examples are the DLLs of the windows OS. They use a clearly defined interface of simple data structures. Memory management and allocation (like windows, menus, GDI objects) is done via a transparent handle. The DLLs are just blackboxes for you.
Hope that I met all points.

Releasing a program

So I made a c++ console game. Now I'd like to "release" the game. I want to only give the .exe file and not the code. How do i go about this. I'd like to make sure it will run on all windows devices.
I used the following headers-
iostream
windows.h
MMSystem.h
conio.h
fstream
ctime
string
string.h
*I used namespace std
*i used code::blocks 13.12 with mingw
& I used the following library-
libwinmm.a
Thank you in advance
EDIT
There are many different ways of installing applications. You could go with an installer like Inno or just go with a regular ZIP file. Some programs can even be standalone by packaging all resources within the executable, but this is not an easy option to my knowledge for C++.
I suppose the most basic way is to create different builds for different architectures with static libraries and then find any other DLLs specific to that architecture and bundle it together in one folder. Supporting x86/x86-64/ARM should be enough for most purposes. I do know that LLVM/Clang and GCC should have extensive support for many architectures, and if need be, you should be able to download the source code of the libraries you use and then compile them for each architecture you plan to support as well as the compilation options you need to compile to each one.
A virtual machine can also be helpful for this cross-compilation and compatibility testing.
tldr; Get all the libraries you need in either static or dynamic (DLL) format. Check that they are of the right architecture (x86 programs/code will not run on MIPS and vice versa). Get all your resources. Get a virtual machine, and then test your program on it. Keep testing until all the dependency problems go away.
Note: when I did this, I actually had some compatibility issues with, of all things, MinGW-w64. Just a note; you may need some DLLs from MinGW, or, if you're using Cygwin, of course you need the Cygwin DLL. I don't know much about MSVC, but I would assume that even they have DLLs needed on some level if you decide to support an outdated Windows OS.

Program which Compile by Code::Block plus MinGW, but Using Standard Windows Library?

everyone.
I am a newer for c++, and I had some experience on c#. I want to create a pure c++ developing environment, and using the standard c++ library. My operation system is Windows.
I choose code::block+MinGW to build a pure developing environment on Windows. I directly choose Code::Block installation packet which integrate MinGW. Then I began to develop my first learning project. And In this project, I used the function "stat" to get file information from standard library. And I passed the compile. But during operation this program, I checked the "Call Stack". And found the function "stat" called from file "C:\WINDOWS\system32\msvcrt.dll". And I checked this dll from internet, and found this file is a microsoft windows library file. So it obviously, this dll file don't have the function "stat", but have the function "_stat".
So how do I solve this problem? I want to use the standard c++ library, not the microsoft windows library. Because later, I want to move this project to linux environment. So overall, how do I build the developing environment to satisfy my requirement.
You have to use the windows system libraries if you're building for Windows. You simply link one or the other depending on the target system. The libraries merely provide the underlying implementation, which is different from one OS to the next.
In your specific example, stat is a function defined by standard system headers, but its underlying implementation will vary from system to system. It's possible that the entire function is pulled from msvcrt, but my guess is that msvcrt happens to implement a companion function which deals with all the system-specific stuff.

Is it possible to use same DLL for clients using both Windows and Linux

I am looking to create a C++ library that can be used by both Linux and Windows clients. The OS specific functionality will be hooked up by the client by implementing the interfaces provided by the library.
Is this possible to achieve? Do I need to recompile the C++ project again in linux.
P.S: I am using CodeBlocks IDE
The short answer is no, you still need to compile your library for each targetted platform -- however, assuming your code is written such that it is cross-platform, you can set up your build to target both Windows and Linux environments with little fuss. I do this now using CMake to generate both Visual Studio projects for Windows environments and Makefiles for Linux environments.
I'm pretty confident that Linux will not accept a .dll :) And yes, you will need to recompile. Unless you run windows as a virtual machine under linux which sort of preempts the question.
It certainly cannot be the same binary file: shared objects ELF format on Linux, DLL "PE" format on Windows. And dynamic loading has different semantics on both systems. See Levine's linker and loader book for details.
You could, if done carefully, have the same source code giving the two different files (the DLL on Windows, the dynamic shared object on Linux).
But you probably would need some conditional compilation tricks like #ifdef WINDOWS etc...
You might use libraries providing you a common abstraction for such things. For instance, both GTK/Glib and Qt have some mechanism giving a common abstraction of dynamically linked (or dynamically loaded - ie dlopen-ed) libraries.
You probably want to read the Program Library Howto (at least for Linux).