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
addthat 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.candexample.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.hheaders, 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_linkerblob
: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.soin 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
.soto.pyd
eg:
_example.sochange to_example.pyd