connect c code to python code with the help of ceedling.
- getting ceedling ready
- install ruby by following this websites
- then install ceedling from command line
gem install ceedling
let's assume we have a c code that add 2 numbers and return the results
int result = add(1, 2);
The aim for swig is to convert the c/c++ code to higher level programming language After generating the wrapper for python code, the above function in c then can be use in python by:
>>>import example
>>>example.add(1, 2)
>>>3
-
create a ceedling project and change directory into it
ceedling new example cd example
-
create a module call add
ceedling module:create[add]
this will create
add.c
,add.h
, andtest_add.c
-
create a function call
add
that adds 2 numbers//add.c int add(int v1, int v2){ return v1 + v2; }
//add.h int add(int v1, int v2);
-
Inorder for swig to generate the wrapper, you need to write an "interface file" which is the input to SWIG.
//add.i %module example %{ /* Includes the header in the wrapper code */ #include "add.h" %} %include "add.h"
-
To turn c code to python module, in command line, type the following:
swig -python add.i
This will create
example_wrap.c
andexample.py
.
-
With the help with ceedling, building and linking the source and object file with gcc can be very easy. You will only have to modify the
project.yml
.- Enable the release build and modify the name of the release output to
_example.so
:project: :release_build: TRUE :release_build: :output: _example.pyd :use_assembly: FALSE
- you can specify the flags of gcc during compiling and linking. Since compiling the wrapper will require
Python.h
headers, we need to also include the directory of Python.h. It's inside path-to-python-install-loc/include
:tools: :release_compiler: :executable: gcc #absolute file path :name: 'gcc linker' :arguments: - -fpic #Compiler directive to output position independent code, a characteristic required by shared libraries - -I"$": COLLECTION_PATHS_TEST_TOOLCHAIN_INCLUDE #expands to -I search paths - -I"$": COLLECTION_PATHS_TEST_SUPPORT_SOURCE_INCLUDE_VENDOR #expands to -I search paths - -IpathToPythonInstallation/include #subtitute with the designated python dir / include - -c ${1} #source code input file (Ruby method call param list sub) - -o ${2} #object file output (Ruby method call param li
- To link all output files to shared library, add in the
release_linker
blob
:release_linker: :executable: gcc #absolute file path :name: 'gcc linker' :arguments: - -shared - ${1} #list of object files to link (Ruby method call param list sub) - -o ${2} #executable file output (Ruby method call param list sub)
- build and link the all the source files in command line by :
ceedling release
this will generate an output product call
_example.so
in build/release- copy _example.so into directory that contains example.py.
to simplify the process or copying, you can modify the output of the products by:
:release_build: :output: ../../directory-containing-example.py/_example.pyd :use_assembly: FALSE
- Enable the release build and modify the name of the release output to
-
Validate the module generated by opening python in that directory and type:
>>>import example >>>example.add(1, 2) >>>3
This is usually due to gcc doesn't link the python library eg. python36.a
during linking of the shared library. Solve this by including the library of python in release_linker blob:
:release_linker:
:executable: gcc #absolute file path
:name: 'gcc linker'
:arguments:
- -shared
- ${1} #list of object files to link (Ruby method call param list sub)
- -LpathToPythonInstallation/libs #subtitute with the path of your python installation
- -lpython36 #subtitue wisely with the version number of the python
- -o ${2} #executable file output (Ruby method call param list sub)
- the shared library name is different from the name from wrapper
eg: in the case of
example.py
, the shared library must be named_example.so
- In windows running mingW, change the extension from
.so
to.pyd
eg:
_example.so
change to_example.pyd