How to wrap a c++ library for python? - c++

I have a library and some head files, no c++ source code, I want to use it with python.
I tried py++, but gccxml report error.
I tried swig, but some many "undefined symbol" errors.
Are there some smart tools can do such things automatically?

You could try using boost python
You'd need to create a simple wrapper dll that links to your original library, containing code similar to this (assuming you wanted to export a class called LibraryClass with 2 functions, foo & bar)
#include <librarytowrap.h>
#include <boost/python.hpp>
using namespace boost::python;
BOOST_PYTHON_MODULE(Library)
{
class_<LibraryClass>("LibraryClass")
.def("foo", &LibraryClass::foo)
.def("bar", &LibraryClass::bar)
;
}
You might be able to use the automatic code generator to read the C++ definitions in the header files and do the hard work for you, but according to the boost python page this is no longer maintained, so I'm unsure how well it works.

Can you not just use the python ctypes package?
See this tutorial.

This approach requires a bit a bit of work, and might not be feasible if you have a lot of functions, that you want to wrap/the functions use a lot of c++ intrinsic types as arguments/return values.
If that is not the case, you can define some c-wrapper functions, with the "extern c" keyword in front of them, with pure c arguments and return types. Compile and link the "wrapper functions" to your c++ library. Then you can use the ctypes module (from python) to call your wrapper functions, which then in turn call the c++ functions in your library.

Related

Mock framework for C Wrappers Around C++ Code

I am working on an API that in wraps C++ behaviors with C calling convention functions. The API is composed of a collection of shared libraries (dll) that may be used in a variety of languages. In instances where a C++ class object is pass across the dll boundary, a C opaque pointer or "Handle" is used to refer to the underlying C++ object, similar to the Win32 API. An example header file prototype of such a wrapper function is
extern "C" { __declspec(dllexport) int __cdecl MyObjConfig(MyObj_t* handle); }
Many of the API functions / classes interface with hardware peripherals. In many cases it's not practical to be able to test on the representative hardware system. I would like to find a way to mock the lower level components so that higher level libraries or exectuables using those libraries can be tested in a simulated environment. However, I'm loathe to include phrases in the underlying source code such as
if(is_test) { return 0; }
For example, I would like to mock the behavior of a function float GetSensorData() so that I can test an executable that links to GetSensorData's parent dll and calls get sensor data, by returning a reasonable imitation of the sensor's normal data, without setting up the sensor explicitly. Also, I would like to avoid having to alter the source of the executable beyond making sure it is linking to an imitation of GetSensorData's dll.
A key part of my interest in an automated framework for creating the dll mocks is that I don't want to have to maintain two seperate versions of each library: a test version and an actual version. Rather I would like to work on the actual and have the "mock" compilation generated programmatically.
Can anyone suggest a good way to do this? I've looked at Gtest and CMock / Unity. Both seem fine for testing the dlls themselves but don't seem well equipped to accomodate the
extern "C" { __declspec(dllexport) int __cdecl
function prototype declarations.
Thanks!
If you have a function that you wish to mock that is located in a library you can either do function pointer substitution or link-time substitution. I wrote about it more in-depth in this answer: https://stackoverflow.com/a/65814339/4441211
I personally recommend the function pointer substitution since it is much more simple and straightforward.

C++ API - what is the right approach

I have to build an API for a C++ framework which do some simulation stuff. I already have created a new class with __declspec(dllexport) functions and built the framework to a DLL.
This works fine and I can use the framework within a C# application.
But is there another or a better approach to create an API with C++?
If you want to create a C++-API, exporting a set of classes from a DLL/shared library is the way to go. Many libraries written in C++ decide to offer a C interface though, because pure C interfaces are much easier to bind to foreign languages. To bind foreign languages to C++, a wrapper generator such as SWIG is typically required.
C++-APIs also have the problem that, due to C++ name-mangling, the same compiler/linker needs to be used to build the framework and the application.
It is important to note that the __declspec(dllexport)-mechanism of telling the compiler that a class should be exported is specific to the Microsoft Compiler. It is common practice to put it into a preprocessor macro to be able to use the same code on other compilers:
#ifdef _MSC_VER
# define MY_APP_API __declspec(dllexport)
#else
# define MY_APP_API
#endif
class MY_APP_API MyClass {}
The solution with exporting classes have some serious drawbacks. You won't be able to write DLLs in another languages, because they don't support name mangling. Furthermore, you won't be able to use other compilers than VS (because of the same reason). Furthermore, you may not be able to use another version of VS, because MS doesn't guarantee, that mangling mechanism stays the same in different versions of the compiler.
I'd suggest using flattened C-style interface, eg.
MyClass::Method(int i, float f);
Export as:
MyClass_MyMethod(MyClass * instance, int i, float f);
You can wrap it inside C# to make it a class again.

shared library symbol names

I would like to be able to use C/C++ functions from python using ctypes python module.
I have a function int doit() in the .c / .cpp file. When I try to load the shared library:
Frr=CDLL("/path/FoCpy2/libFrr.so")
Frr.doit(c_int(5))
i find it working really well when the .c variant is used. When C++ is called the good way to call this function is (found out using nm libFrr.so using nm -gC libFrr.so produces just plain doit()):
Frr._Z4doitv(c_int(5))
I have read on Stackexchange that there is no standard way to call C++ from python, and there is "nonstandard name mangling" issue. Is the "Z4" a part of that issue? I guess the nonstandard name mangling would appear for more advanced language features such as class methods, templates, but also for such basic functions? Is it possible to force using simple C function names in simple cases for the C++ code?
You can use extern "C" to make the functions "look like" C functions to the outside world (i.e., disable name-mangling). And yes, you are correct, name-mangling is needed mostly for the more complicated features and types of functions that C++ has, and the name-mangling scheme has never been standardized (nor the binary compatibility) and so it varies from compiler to compiler and between versions (but most main-stream compilers have settled to something permanent now, but still different between compiler-vendors). And the reason that mangling is also required for plain old free functions is because C++ supports overloading (same function names but with different parameters), and thus, the compilers will encode the parameter specification (e.g., types) into the mangled names. Of course, if you use extern "C" you lose all features for which name-mangling is needed, so, it more or less boils down to C functions only.
You can use extern "C" either on a per-function basis, like so:
extern "C" int doit();
Or for the overall header:
extern "C" {
// all the function declarations here ...
};
However, for Python specifically, I highly recommend that you use a library that allows you to construct Python classes and functions that are a reflection of your C++ classes and functions, that makes life a lot easier and hides away all this extern "C" business. I recommend using Boost.Python, see this getting started page, it makes exporting functions and classes to Python a breeze. I guess others would also recommend SWIG, but I have never used it.
Calling c++ library functions is always a mess, actually even if you're using C++ you have to use the same compiler, etc. to make sure it works.
The only general solution is to define your c++ functions as extern "C" and make sure you follow the involved limitations - see here for an explanation of it.

class functions[C++] call function that does not belong to any class

I have a small doubt.
I am adding some extra functions in a C++ code and these functions are getting called by functions of a class.
Is it necessary to make these extra functions a part of class or can a C++ class function call a C function?
If yes, how should the makefile be modified ?
Thanks!
As long as you have included some declaration and the C function is linked in it some point in the compilation, you can call C functions in any C++ function. For instance:
mycfunc.h:
void test(int x);
myfunc.c:
void test(int x) {
printf("%d\n", x);
}
Now, simply include the header file where you want to use the function. In your Makefile, simply make sure you include "myfunc.c" (or .o if you're compiling objects) in the final compilation.
C++ is not a pure object oriented language.
So you can use imperative form as it is in C ( even if it's modular or not ).
Some C functions not encapsulated in Objects are accessible using c* includes (ctime for instance).
You do not need to put them in a class. Functions exist in C++ just as in C so you can just use them. Just try it and ask again if you have trouble.
As you state that you add functions to a C++ project, just treat (and think of) all your code as C++. Put your new stuff in files using the same filename extensions as those of the rest of the project.
Edit in response to comment from OP:
Yes, no need to think about the distinction between C and C++ in this case. Just write .cpp files. And in the makefile, just add those files just as the other files are listed there.
The distinction between C and C++ is important if you have existing C++ code and need to use if from C, or for example if you have existing C libraries and need to call that from C++. In your case there's very likely no reason not to stick to C++. Unlike Java, it's completely natural to have free standing functions. There even many in the C++ standard library.
Now, if in your case it is good design to have free standing functions instead of adding to classes (modifying or using inheritance) is hard to tell given the information you have posted. But, if what you need to do can be done in a natural way without accessing the private parts of existing classes the answer may very well be yes.

Can I use C++ features while extending Python?

The Python manual says that you can create modules for Python in both C and C++. Can you take advantage of things like classes and templates when using C++? Wouldn't it create incompatibilities with the rest of the libraries and with the interpreter?
It doesn't matter whether your implementation of the hook functions is implemented in C or in C++. In fact, I've already seen some Python extensions which make active use of C++ templates and even the Boost library. No problem. :-)
The boost folks have a nice automated way to do the wrapping of C++ code for use by python.
It is called: Boost.Python
It deals with some of the constructs of C++ better than SWIG, particularly template metaprogramming.
What you're interested in is a program called SWIG. It will generate Python wrappers and interfaces for C++ code. I use it with templates, inheritance, namespaces, etc. and it works well.
You should be able to use all of the features of the C++ language. The Extending Python Documentation (2.6.2) says that you may use C++, but mentions the followings caveats:
It is possible to write extension
modules in C++. Some restrictions
apply. If the main program (the Python
interpreter) is compiled and linked by
the C compiler, global or static
objects with constructors cannot be
used. This is not a problem if the
main program is linked by the C++
compiler. Functions that will be
called by the Python interpreter (in
particular, module initialization
functions) have to be declared using
extern "C". It is unnecessary to
enclose the Python header files in
extern "C" {...} — they use this form
already if the symbol __cplusplus is
defined (all recent C++ compilers
define this symbol).
The first restriction, "global or static objects with constructors cannot be used", has to do with the way most C++ compiler initialize objects with this type of storage duration. For example, consider the following code:
class Foo { Foo() { } };
static Foo f;
int main(int argc, char** argv) {}
The compiler has to emit special code so that the 'Foo' constructor gets invoked for 'f' before main gets executed. If you have objects with static storage duration in your Python extension and the Python interpreter is not compiled and linked for C++, then this special initialization code will not be created.
The second restriction, "Functions that will be called by the Python interpreter (in particular, module initialization functions) have to be declared using extern "C"", has to do with C++ name mangling. Most C++ compilers mangle their names so that they can use the same linkers provided for C toolchains. For example say you had:
void a_function_python_calls(void* foo);
the C++ compiler may convert references to the name 'a_function_python_calls' to something like 'a_function_python_calls#1vga'. In which case you may get an unresolved external when trying to link with the Python library.