How to wrap a pure C library (instead of C++)

Asked by vilmos

Hi,

I would like to create python bindings for a C library. It seems pybindgen generates C++ code when Module.generate() is called, and I can indeed compile and link this .cc file with g++ (I also add -lmylib so that my lib is linked with the shared object). However, if I try to import this shared object module from python it complains about unresolved symbols:

<type 'exceptions.ImportError'>: ./pymylib.so: undefined symbol: _Z12mylib_setP15mylib_structxP8mylib_structy

What am I doing wrong?

Thanks
Vilmos

Question information

Language:
English Edit question
Status:
Solved
For:
PyBindGen Edit question
Assignee:
No assignee Edit question
Solved by:
Gustavo Carneiro
Solved:
Last query:
Last reply:
Revision history for this message
Best Gustavo Carneiro (gjc) said :
#1

Since you generate to a .cc file and compile with g++, the compiler will assume every external function declaration is a C++ function, which has different name mangling than C (remember C++ supports function signature overloading).

You can keep the .cc file and g++, but then you have to make sure the external functions are declared as C functions:

extern "C" {

  mylib_func (whatever);

}

Most C libraries support C++ compilers by using this in the header file:

#ifdef __cplusplus
extern "C" {
#endif

  mylib_func (whatever);

#ifdef __cplusplus
}
#endif

Another option is to simply generate the code into a .c file and compile with gcc instead of g++. Unless you wrap C++ related features, this will usually work. There's a tests/c-hello with a unit test for pure C code generation, that can also serve as example if nothing better.

Revision history for this message
vilmos (vilmos) said :
#2

Thanks for the quick answer Gustavo. I tried to read through all the docs I could find, however I still don't know how to make pybindgen generate C code instead of C++ (seems that C++ is the default?). Any suggestions?

Revision history for this message
Gustavo Carneiro (gjc) said :
#3

There is no magical switch to generate C instead of C++.

It just happens that if you are wrapping C APIs then the generated code is supposed to be C compatible and can be compiled by a C compiler. Just try it... :-)

Revision history for this message
vilmos (vilmos) said :
#4

It seems that C++ code is generated even though I wrap a C library... I'm just trying to wrap a few functions and struct definitions.

Anyway, wrapping the headers with extern "C" {} did the trick. Thanks for the prompt help!

Revision history for this message
vilmos (vilmos) said :
#5

Thanks Gustavo Carneiro, that solved my question.

Revision history for this message
Gustavo Carneiro (gjc) said :
#6

OK. I try to generate code compatible with C when wrapping only C APIs, but sometimes I fail (which I consider a bug).