python和c++互调

1. C/C++调python
    一.关于python库,http://www.python.org/可以从这里下载,编译得到release和debug库。
    二.被调python文件不含有住函数,不能有变量,内存需C/C++来分配。 

[python] view plain copy print ?
  1. test.py  
  2. def print_list(list):  
  3.     print dict  
  4. def show():  
  5.     print "hello world"  

[cpp] view plain copy print ?
  1. test.cpp 代码其它地方拉来  
  2. #include "Python.h"   
  3. #include "Python.h"   
  4. int main(int argc, char** argv)  
  5. {  
  6.     //初始化Python   
  7.     //在使用Python系统前,必须使用Py_Initialize对其   
  8.     //进行初始化。它会载入Python的内建模块并添加系统路   
  9.     //径到模块搜索路径中。这个函数没有返回值,检查系统   
  10.     //是否初始化成功需要使用Py_IsInitialized。   
  11.   
  12.     Py_Initialize();  
  13.   
  14.     // 检查初始化是否成功   
  15.     if ( !Py_IsInitialized() ) {  
  16.         return -1;  
  17.     }  
  18.   
  19.     //添加当前路径   
  20.     //把输入的字符串作为Python代码直接运行,返回0   
  21.     //表示成功,-1表示有错。大多时候错误都是因为字符串   
  22.     //中有语法错误。   
  23.     PyRun_SimpleString("import sys");  
  24.     PyRun_SimpleString("sys.path.append('./')");  
  25.     PyObject *pName,*pModule,*pDict,*pFunc,*pArgs;  
  26.   
  27.     // 载入名为test的python脚本   
  28.     pName = PyString_FromString("test");  
  29.     pModule = PyImport_Import(pName);  
  30.     if ( !pModule ) {  
  31.         printf("can't find test.py");  
  32.         getchar();  
  33.         return -1;  
  34.     }  
  35.     pDict = PyModule_GetDict(pModule);  
  36.     if ( !pDict ) {  
  37.         return -1;  
  38.     }  
  39.   
  40.     // 找出函数名为print_list的函数   
  41.     pFunc = PyDict_GetItemString(pDict, "print_list");  
  42.     if ( !pFunc || !PyCallable_Check(pFunc) ) {  
  43.         printf("can't find function [add]");  
  44.         getchar();  
  45.         return -1;  
  46.     }  
  47.     // 参数进栈   
  48.     *pArgs;  
  49.      pArgs = PyTuple_New(2);  
  50.   
  51.     // PyObject* Py_BuildValue(char *format, ...)   
  52.     // 把C++的变量转换成一个Python对象。当需要从   
  53.     // C++传递变量到Python时,就会使用这个函数。此函数   
  54.     // 有点类似C的printf,但格式不同。常用的格式有   
  55.     // s 表示字符串,   
  56.     // i 表示整型变量,   
  57.     // f 表示浮点数,   
  58.     // O 表示一个Python对象。   
  59.   
  60.     PyTuple_SetItem(pArgs, 0, Py_BuildValue("i",3));  
  61.     PyTuple_SetItem(pArgs, 1, Py_BuildValue("i",4));  
  62.   
  63.     // 调用Python函数   
  64.     PyObject_CallObject(pFunc, pArgs);  
  65.   
  66.     //下面这段是查找函数foo 并执行foo   
  67.     pFunc = PyDict_GetItemString(pDict, "foo");  
  68.     if ( !pFunc || !PyCallable_Check(pFunc) ) {  
  69.         printf("can't find function [foo]");  
  70.         getchar();  
  71.         return -1;  
  72.     }  
  73.   
  74.     pArgs = PyTuple_New(1);  
  75.     PyTuple_SetItem(pArgs, 0, Py_BuildValue("i",2)); //   
  76.   
  77.     PyObject_CallObject(pFunc, pArgs);  
  78.   
  79.     Py_DECREF(pName);  
  80.     Py_DECREF(pArgs);  
  81.     Py_DECREF(pModule);  
  82.   
  83.     // 关闭Python   
  84.     Py_Finalize();  
  85.   
  86.     return 0;  
  87. }  
编译 g++ test.cpp -o cpython -I/usr/include/python2.7 -L/usr/lib/python2.7 -lpython2.7


2. python调C/C++
Python调用C动态链接库
Python调用C库很简单,不经过任何封装打包成so,再使用python的ctypes调用即可。
[cpp] view plain copy print ?
  1. <test.cpp 生成动态库的源文件>  
  2. #include <stdio.h>   
  3. extern "C" {  
  4.     void display() {  
  5.         printf("This is Display Function\n");  
  6.     }  
  7. }  
这里需要注意的是:使用g++编译生成动态库的代码中的函数或者方法时, 需要使用extern "C"来进行编译
g++ test.cpp -fPIC -shared -o libtest.so

[python] view plain copy print ?
  1. <call.py 调用动态库的源文件>  
  2. import ctypes  
  3. so = ctypes.CDLL("./libtest.so")    
  4. so.display()  

Python调用C++(含类,重载)动态链接库
但是调用C++的so就有点麻烦了,网上找了下,大部分都是需要extern "C" 来辅助,也就是说还是只能调用C函数 不能直接调用方法 但是能解析C++方法。
[cpp] view plain copy print ?
  1. <test.cpp 生成动态库的源文件>  
  2. #include <Akita/Akita.h>   
  3. class TestLib  
  4. {  
  5. public:  
  6.     void display();  
  7.     void display(int a);  
  8. };  
  9.   
  10. void TestLib::display()  
  11. {  
  12.     cout<<"First display"<<endl;  
  13. }  
  14.   
  15. void TestLib::display(int a) {  
  16.     cout<<"Second display"<<endl;  
  17. }  
  18.   
  19. extern "C" {  
  20. TestLib obj;  
  21.     void display()  
  22.     {  
  23.         obj.display();  
  24.     }  
  25.     void display_int()  
  26.     {  
  27.         obj.display(2);  
  28.     }  
  29. }  
g++ test.cpp -fPIC -shared -o libtest.so
使用这种方法有点麻烦 但是可以解决问题。注意到后面还是会有个extern "C" 不然构建后的动态链接库没有这些函数的符号表的。

[python] view plain copy print ?
  1. <call.py 调用动态库的源文件>  
  2. import ctypes  
  3. so = ctypes.CDLL("./libtest.so")  
  4. so.display()  
  5. so.display_int(1)  


运行结果如下:
^[root@:~/Projects/nugget/kvDB-py]#python call.py   
First display
Second display


C/C++调用Python模块
[cpp] view plain copy print ?
  1. <test.cpp >  
  2. #include <Akita/Akita.h>   
  3. #include <Python.h>   
  4. int main()  
  5. {  
  6.     Py_Initialize();  
  7.     if (!Py_IsInitialized())  return FALSE  
  8.     PyRun_SimpleString("import sys");  
  9.     PyRun_SimpleString("sys.path.append('./')");  
  10.   
  11.     //import Module   
  12.     PyObject* pModule = PyImport_ImportModule("hello");  
  13.     if (!pModule) {  
  14.         cout<<"Can't import Module!/n"<<endl;  
  15.         return -1;  
  16.     }  
  17.   
  18.     PyObject* pDict = PyModule_GetDict(pModule);  
  19.     if (!pDict) {  
  20.         return -1;  
  21.     }  
  22.   
  23.     //fetch Function   
  24.     PyObject* pFunHi = PyDict_GetItemString(pDict, "display");  
  25.     PyObject_CallFunction(pFunHi, "s""Crazybaby");  
  26.     Py_DECREF(pFunHi);  
  27.   
  28.     //Release   
  29.     Py_DECREF(pModule);  
  30.     Py_Finalize();  
  31.     return 0;  
  32. }  
#g++ test.cpp -I/usr/local/include/python2.7 -ldl -lutil -lpthread -lpython2.7

[python] view plain copy print ?
  1. <call.py>  
  2. def display(name):  
  3.     print "hi",name  


C++为Python编写扩展模块
Python为C++提供脚本接口。

你可能感兴趣的:(python和c++互调)