python和c++互调

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

  1. test.py  
  2. def print_list(list):  
  3.     print dict  
  4. def show():  
  5.     print "hello world"  
test.py
def print_list(list):
    print dict
def show():
    print "hello world"

  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. }  
test.cpp 代码其它地方拉来
#include "Python.h"
#include "Python.h"
int main(int argc, char** argv)
{
    //初始化Python
    //在使用Python系统前,必须使用Py_Initialize对其
    //进行初始化。它会载入Python的内建模块并添加系统路
    //径到模块搜索路径中。这个函数没有返回值,检查系统
    //是否初始化成功需要使用Py_IsInitialized。

    Py_Initialize();

    // 检查初始化是否成功
    if ( !Py_IsInitialized() ) {
        return -1;
    }

    //添加当前路径
    //把输入的字符串作为Python代码直接运行,返回0
    //表示成功,-1表示有错。大多时候错误都是因为字符串
    //中有语法错误。
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append('./')");
    PyObject *pName,*pModule,*pDict,*pFunc,*pArgs;

    // 载入名为test的python脚本
    pName = PyString_FromString("test");
    pModule = PyImport_Import(pName);
    if ( !pModule ) {
        printf("can't find test.py");
        getchar();
        return -1;
    }
    pDict = PyModule_GetDict(pModule);
    if ( !pDict ) {
        return -1;
    }

    // 找出函数名为print_list的函数
    pFunc = PyDict_GetItemString(pDict, "print_list");
    if ( !pFunc || !PyCallable_Check(pFunc) ) {
        printf("can't find function [add]");
        getchar();
        return -1;
    }
    // 参数进栈
    *pArgs;
     pArgs = PyTuple_New(2);

    // PyObject* Py_BuildValue(char *format, ...)
    // 把C++的变量转换成一个Python对象。当需要从
    // C++传递变量到Python时,就会使用这个函数。此函数
    // 有点类似C的printf,但格式不同。常用的格式有
    // s 表示字符串,
    // i 表示整型变量,
    // f 表示浮点数,
    // O 表示一个Python对象。

    PyTuple_SetItem(pArgs, 0, Py_BuildValue("i",3));
    PyTuple_SetItem(pArgs, 1, Py_BuildValue("i",4));

    // 调用Python函数
    PyObject_CallObject(pFunc, pArgs);

    //下面这段是查找函数foo 并执行foo
    pFunc = PyDict_GetItemString(pDict, "foo");
    if ( !pFunc || !PyCallable_Check(pFunc) ) {
        printf("can't find function [foo]");
        getchar();
        return -1;
    }

    pArgs = PyTuple_New(1);
    PyTuple_SetItem(pArgs, 0, Py_BuildValue("i",2)); //

    PyObject_CallObject(pFunc, pArgs);

    Py_DECREF(pName);
    Py_DECREF(pArgs);
    Py_DECREF(pModule);

    // 关闭Python
    Py_Finalize();

    return 0;
}
编译 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调用即可。
  1. <test.cpp 生成动态库的源文件>  
  2. #include <stdio.h>   
  3. extern "C" {  
  4.     void display() {  
  5.         printf("This is Display Function\n");  
  6.     }  
  7. }  
<test.cpp 生成动态库的源文件>
#include <stdio.h>
extern "C" {
    void display() {
        printf("This is Display Function\n");
    }
}
这里需要注意的是:使用g++编译生成动态库的代码中的函数或者方法时, 需要使用extern "C"来进行编译
g++ test.cpp -fPIC -shared -o libtest.so

  1. <call.py 调用动态库的源文件>  
  2. import ctypes  
  3. so = ctypes.CDLL("./libtest.so")    
  4. so.display()  
<call.py 调用动态库的源文件>
import ctypes
so = ctypes.CDLL("./libtest.so")  
so.display()

Python调用C++(含类,重载)动态链接库
但是调用C++的so就有点麻烦了,网上找了下,大部分都是需要extern "C" 来辅助,也就是说还是只能调用C函数 不能直接调用方法 但是能解析C++方法。
  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. }  
<test.cpp 生成动态库的源文件>
#include <Akita/Akita.h>
class TestLib
{
public:
    void display();
    void display(int a);
};

void TestLib::display()
{
    cout<<"First display"<<endl;
}

void TestLib::display(int a) {
    cout<<"Second display"<<endl;
}

extern "C" {
TestLib obj;
    void display()
    {
        obj.display();
    }
    void display_int()
    {
        obj.display(2);
    }
}
g++ test.cpp -fPIC -shared -o libtest.so
使用这种方法有点麻烦 但是可以解决问题。注意到后面还是会有个extern "C" 不然构建后的动态链接库没有这些函数的符号表的。

  1. <call.py 调用动态库的源文件>  
  2. import ctypes  
  3. so = ctypes.CDLL("./libtest.so")  
  4. so.display()  
  5. so.display_int(1)  
<call.py 调用动态库的源文件>
import ctypes
so = ctypes.CDLL("./libtest.so")
so.display()
so.display_int(1)


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


C/C++调用Python模块
  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. }  
<test.cpp >
#include <Akita/Akita.h>
#include <Python.h>
int main()
{
    Py_Initialize();
    if (!Py_IsInitialized())  return FALSE
    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path.append('./')");

    //import Module
    PyObject* pModule = PyImport_ImportModule("hello");
    if (!pModule) {
        cout<<"Can't import Module!/n"<<endl;
        return -1;
    }

    PyObject* pDict = PyModule_GetDict(pModule);
    if (!pDict) {
        return -1;
    }

    //fetch Function
    PyObject* pFunHi = PyDict_GetItemString(pDict, "display");
    PyObject_CallFunction(pFunHi, "s", "Crazybaby");
    Py_DECREF(pFunHi);

    //Release
    Py_DECREF(pModule);
    Py_Finalize();
    return 0;
}
#g++ test.cpp -I/usr/local/include/python2.7 -ldl -lutil -lpthread -lpython2.7

  1. <call.py>  
  2. def display(name):  
  3.     print "hi",name  
<call.py>
def display(name):
    print "hi",name


C++为Python编写扩展模块
Python为C++提供脚本接口。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值