Python/C API
C Codes
demo.c
int add(int x, int y){ return x + y; } //int main(void){ // printf("%d", add(1, 2)); // return 0; //} #include<Python.h> static PyObject* W_add(PyObject* self, PyObject* args){ int x; int y; if(!PyArg_ParseTuple(args, "i|i", &x, &y)){ return NULL; } else { return Py_BuildValue("i", add(x, y)); } } static PyMethodDef ExtendMethods[] = { {"add", W_add, METH_VARARGS, "a function from C"}, {NULL, NULL, 0, NULL}, }; //initxxx, xxx should be this file name //if spam.c => spam.so //when import spam will raise ImportError //ImportError: dynamic module does not define init function (initspam) //-o xxx.so, xxx also should be this file name PyMODINIT_FUNC initdemo(){ Py_InitModule("demo", ExtendMethods); }
Compilation and Linkage
Command
gcc demo.c -I /usr/include/python2.6 -shared -o demo.so
Ubuntu 12.04.5 LTS
raise error$ gcc demo.c -I /usr/include/python2.7 -shared -o demo.so /usr/bin/ld: /tmp/cceeXldr.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC /tmp/cceeXldr.o: could not read symbols: Bad value collect2: ld returned 1 exit status
Recompile with
-fPIC
worksgcc demo.c -I /usr/include/python2.6 -shared -fPIC -o demo.so
Mac OS X
raise error$ gcc demo.c -I /usr/include/python2.7 -shared -o demo.so Undefined symbols for architecture x86_64: "_PyArg_ParseTuple", referenced from: _W_add in demo-00439c.o "_Py_BuildValue", referenced from: _W_add in demo-00439c.o "_Py_InitModule4_64", referenced from: _initdemo in demo-00439c.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)
Tips
if note off main function
$ gcc demo.c -I /usr/include/python2.7 -shared -fPIC -o demo.so demo.c: In function ‘main’: demo.c:6:5: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
and not note off printf works
int main(void){ // printf("%d", add(1, 2)); return 0; }
Python Building Extension
Setup.py
https://github.com/urwid/urwid/blob/master/setup.py
building 'urwid.str_util' extension creating build/temp.macosx-10.9-intel-2.7 creating build/temp.macosx-10.9-intel-2.7/source cc -fno-strict-aliasing -fno-common -dynamic -arch x86_64 -arch i386 -g -Os -pipe -fno-common -fno-strict-aliasing -fwrapv -DENABLE_DTRACE -DMACOSX -DNDEBUG -Wall -Wstrict-prototypes -Wshorten-64-to-32 -DNDEBUG -g -fwrapv -Os -Wall -Wstrict-prototypes -DENABLE_DTRACE -arch x86_64 -arch i386 -pipe -I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -c source/str_util.c -o build/temp.macosx-10.9-intel-2.7/source/str_util.o cc -bundle -undefined dynamic_lookup -arch x86_64 -arch i386 -Wl,-F. build/temp.macosx-10.9-intel-2.7/source/str_util.o -o build/lib.macosx-10.9-intel-2.7/urwid/str_util.so
References
[1] Docs@Python, Extending Python with C or C++
[2] Docs@Python, Python/C API Reference Manual
[3] O'Reilly's CD bookshelf, 24.1 Extending Python with Python's C API
[4] user1667191@StackOverflow, Compilation fails with “relocation R_X86_64_32 against `.rodata.str1.8' can not be used when making a shared object”