cpp2any
What is it?
cpp2any is a universal interface generator: in other words, it is a tool which can be used to create, fully automatically, the wrappers allowing an existing C++ library to be used from almost any other language. It is capable of reading the existing C++ source files and produces the necessary glue to allow the library functionality to be used across the language boundary. The interface generator is not tied to a particular library nor a particular target language and so provides a very flexible solution for the library users who wish to work with it from their favourite language or development environment.
cpp2any has been developed by TT-Solutions in collaboration with ITO 33, a renowned financial software solutions provider company. Although the development work on it still continues, it is already used for several important projects by ITO 33 and others.
How does it work?
Hello, cpp2any!
To show cpp2any on a really simple example, please consider this file:
/**
A really simple class.
*/
class Hello
{
public:
/**
A very simple function which just shows a
message box to the user.
@param num the number to show to the user
*/
void ShowNumber(int num);
};
Let us now run the interface generator telling it to use the templates from mytemplates directory (more about this later) and generating the wrappers for COM only:
C:\>cpp2any /tmytemplates /fCOM /DLIBRARY=HelloLib hello.h
This is going to generate the following files:
- include/COM/hello.h
- src/COM/hello.cpp
- hello.idl
The location of these files can be changed with the appropriate command line options, please see the manual and their contents is not really important for us right now. What is important is that after building them together with the file implementing the class declared in hello1.h (it can be found in hello1.cpp in cpp2any distribution) we obtain a ready to use in process COM server which can now be called from any COM-compatible language. For example, here is how it is used from Microsoft Visual Basic (or Visual Basic for Applications):
Attribute VB_Name = "Hello1"
Sub Main()
Dim hi As New Hello
hi.ShowNumber 17
End Sub
And here is how it is used from Python:
#!/usr/bin/python
import win32com.client
hi = win32com.client.Dispatch("HelloLib.Hello")
hi.ShowNumber(17)
Of course, our newly created server may also be used from other languages such as Java, Perl, Ruby, VBScript and JavaScript (which allows to embed it inside the web pages) or even C and C++ although arguably it could be preferable to use the initial C++ class directly in the latter case.
Some explanations
Of course, the example shown so far mostly looks like some black magic as we haven't explained quite a few things. Let us try to shed some light on them in order of importance.
Templates
Flexibility of cpp2any is due to its use of templates. These templates don't have anything to do with C++ template keyword so please don't confuse them. Rather, the cpp2any templates are the files telling it what exactly should it generate on output for the given C++ input.
Different template files are used for each back-end, that is different templates are needed for C and COM back-ends. C templates are relatively simple while the ones for COM are more complicated as they require the support code needed to create a COM server. The same is true for most of the others, including the XLL backend. Although we do provide these templates with cpp2any, it is perfectly possible and, in fact, encouraged, to write new ones. For example, if you are already using Microsoft MFC or ATL libraries you may want to prefer to write a template for generating COM servers using them instead of the custom COM-support code on which the standard COM template relies. Please see the templates writer guide to learn more than you ever wanted to know about cpp2any templates.
Variables
The /DLIBRARY=HelloLib part of the command line defines a template variable called LIBRARY with the given value. This variable is used by the standard COM template to define the name of the COM library which is going to be created. It is more convenient to define it on the command line instead of inside the hello.h file itself because in real life there are going to be many (sometimes dozens or more) of the header files and we don't want to duplicate the library name for all of them. Alternative solution for such global variables in the next version of cpp2any will be to use a configuration file — but for now it has to be given on the command line.
Special C++ comments
Last thing we haven't explained are the strangely looking comments in the hello.h file. You may have recognized them as doxygen comments but even so you probably have never encountered the @iid construction before.
This is an example of defining variables inside the C++ file itself. Each C++ class must have an associated IID, or interface identifier, to be used from COM. You may either specify it on the command line, as above, by doing /DIID_ClassName=... or put it in the file itself. As the IIDs never change, the latter choice is usually the best one.
More special comments exist and are described in the manual.
Further ahead
Of course, the example considered so far was really trivial and there wouldn't be much interest in cpp2any if this were all it could do. Luckily, there is more — much more in fact:
- cpp2any supports all standard C types and not only int, including support for strings (see hello2.h)
- It also has built in support for standard C++ classes such as std::string (see hello2b.h) and std::vector (see hello4.h) and even the auto pointers (see hello5.h)
- User-defined classes can be passed and returned from the methods just as easily as built-in types (see hello3.h and hello3b.h)
Credits
For the curious, cpp2any itself is written in portable C++ and so can run on any platform (even if the generated files for some back-ends, notably COM and XLL, can only be built under Windows). It is partly based on SWIG and we wish to express our thanks to SWIG developers.