Wrapping pygtk widgets – what you should know
In past days I’ve encountered a series of problems. In this article I will explain what kind of problem one can found and how to solve this problems.
I’ve some hints:
- Study the C syntax and the pointers , skip all the algorithmic part: it’s not useful for wrapping a python module.
- It’s useful to study some C++ for design purposes, the C manuals doesn’t face well the multiple-file programs, compilation, headers topics… In C++ this is necessary and well explained in manuals.
- The most important thing you should know is how to read (and write ) simple Makefiles, I’ve tried to learn autotools but they are very hard to understand.
Libraries and python modules
A python module (from a C wrapper) is a shared library. What’s shared, and what’s library? Let’s explain with a simple example.
Suppose you are a mathematician and you’ve coded in C your ugly formulas. You want to use this formulas in other programs.
The best solution is to split your program in three files:
- main.c : Run the program, using the functions you specify in other files.( includes headers files like ugly-functions.h to define the fuctions prototypes)
- ugly-functions.h : here are the function prototipes, each function is declared and explained in an human-readable format ( a lot of comments)
- ugly-functions.c : here are the function implementations, you code what each function do.
Well, it’s time to compile your boring program. You can compile with:
gcc ugly-functions.c main.c -o boring-program
Another way, more interesting:
gcc -c ugly-functions.c # The output is a file called ugly-functions.o gcc -c main.c # main.o gcc main.o ugly.functions.o -o boring-program # This phase is called linking
With the first two commands you create object files. With the last command you link the so called object-files in an executable form.
The -c option tells gcc to don’t call the linker. The linker links the function implementations to their name. (otherwise main.c couldn’t find the function implementations).
Now you can found other formulas and code them in another file: good-formulas.c.
You make your header file(.h), and your source file (.c), now you can compile with the same command.
gcc -c ugly-functions.c # The output is a file called ugly-functions.o gcc -c good-formulas.c # good-formulas.o gcc -c main.c # main.o gcc main.o ugly.functions.o good-formulas.o -o interesting-program
Ok you have obtained your interesting program with your new good formulas. Now you may want to transform them in libraries.
To make a static library, you can group (archive) your object-files in a single file with this command:
ar rcs libmine.a ugly-functions.o good-formulas.o
now with this archive you can link your functions to the main program in this way:gcc main.o libmine.a -o interesting-program
OK. You’ve done our static library. You’ve copied in the final executable all the object-files. When there are a lot of object-files the executable will growth in dimension. Here comes the shared libraries.
A note before proceeding, static libraries are discouraged in general.
Now there’s the most important part of the tutorial. Because python modules are shared libraries.
To make a shared library, you have to recompile your .c files in a special manner, with the -fPIC option: this makes the library to be loaded and referenced at run time.gcc -c -fPIC ugly-functions.c gcc -c -fPIC good-formulas.c
Now we can create the library, libmine.so :gcc -shared ugly-functions.o good-formulas.o -o libmine.so
Now it’s time to link, you can use the same method:gcc main.o libmine.so -o interesting-program
There’s another way to link the program, that is mostly used:gcc -L/directory/containing/library -lmine main.o -o interesting-program
The -l option specifies which library to link when you use this you have to omit the lib prefix and the .so suffix (if there isn’t the lib prefix you have to omit only the .so suffix).
The -L option specifies the path where to find the library.
Remember this options that are widely used in Makefiles.
Now this library can be used by a lot of programs and it’s linked at runtime but it has to be reachable. If you run the program you will catch this error:./interesting-program: error while loading shared libraries: libmine.so: cannot open shared object file: No such file or directory
You have to tell to the system where to find the library, you can put it in a standard location like /usr/lib or you can use the variable LD_LIBRARY_PATH.export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/directory/containing/library
Re-run and it should be ok. There are a lot of other problems you can encounter, mostly related to the file you have linked in the library.
What you should take at home
When you compile python module in a shared library you can encounter a lot of problems:
- Sure you that you have compiled ALL the object files with the -fPIC option
- You must include all the libraries that contains the functions defined. Otherwise you will encounter “undefined symbol” errors.
- Others that now I can’t remember