Python调用C++
- 编译C++源码
本文主要讲述的是Python扩展方式调用C++库,本例中使用的第三方库是Snmp++。读者请自行到官网下载源码编译安装,这里不在详细的说明。
/*client_intf_cxx_wrap.cpp*/
#include "Python.h"
#include <iostream>
#include <libsnmp.h>
#include <snmp/snmp_pp.h>
using namespace std;
#include "Python.h"
#include <iostream>
#include <snmp/libsnmp.h>
#include <snmp_pp.h>
using namespace std;
class TestSnmp
{
public:
TestSnmp();
~TestSnmp();
void PrintHelloWorld();
};
TestSnmp::TestSnmp()
{
Oid oid; //Snmp++的Oid对象。
}
TestSnmp::~TestSnmp()
{
}
void PrintHelloWorld()
{
cout << "Hello world!" <<endl;
}
static PyObject* snmp_get(PyObject* self, PyObject* args)
{
TestSnmp mTestSnmp;
mTestSnmp.PrintHelloWorld();
cout << " snmp_get: " << " get commond" << endl;
return (PyObject*)Py_BuildValue("");
}
static PyMethodDef ClientMethods[] =
{
{"get", snmp_get, METH_VARARGS},
{NULL,NULL},
};
extern "C" void initclient_intf_cxx()
{
Py_InitModule("client_intf_cxx", ClientMethods);
}
编译上述代码可以通过两种方式,distutils和g++。
1. distutils
Python自带工具distutils是用来编译、安装、分发模块等的,创建一个setup.py的python脚本,如:
"""
setup.py
"""
from distutils.core import setup, Extension
client_intf_cxx_module = Extension('_client_intf_cxx',
sources=['client_intf_cxx_wrap.cpp'],
)
setup (name = 'client_intf_cxx',
version = '0.1',
author = "Snmp Docs",
description = """Simple snmp example from docs""",
ext_modules = [client_intf_cxx_module],
py_modules = ["client_intf_cxx"],
)
接着执行编译命令:
python setup.py build_ext --inplace
在当前目录下就可以找到编译好的模块。
2. g++
如果不喜欢使用自动化配置的方式,也可以使用g++来编译。通过g++ 生成共享库。
直接使用下面的命令生成共享库:
g++ -shared -fPIC client_inf_cxx.cc -o libclient_intf_cxx.so -I/**python.h头文件的目录** -L/**snmp库的目录** -lsnmp++
-shared:表示生成共享库
-fPIC: 表示在编译时采用的是相对地址方式。
-o: 表示生成的目标文件名称,如client_intf_cxx.so
-I: 表示指定的头文件包含目录,此处是Python的头文件包含目录,代码中包含的snmp头文件安装在/usr/include下。
-L(大写):表示snmp++库所在目录
-l(小写L):表似乎snmp++库的名称,不是库文件(libsnmp++.so.*)的名称,而是snmp++。
- Python调用库
生成好库文件后,在Python中有两种方式调用:ctypes和import。
- ctypes导入
import ctypes
so = ctypes.cdll.LoadLibrary
lib = so("./libclient_intf_cxx.so")
lib.get()
- import导入
直接写python文件,如pytest.py,通过Python执行脚本。
- ctypes导入
import libclient_intf_cxx as snmp
snmp.get()
SWIG
SWIG(Simplified Wrapper and Interface Generator ),SWIG 允许您向广泛的脚本语言公开 C/C++ 代码,包括 Ruby、Perl、Tcl 和 Python等。
为了建立python的扩展模块,SWIG采用分层的策略:用c写扩充模块,其余部分用python写。c包含低层次的封装,而python包含高层次的封装。分层策略是扩展模块的特定部分用特定的语言完成(而不全部用c/c++完成),另外通过利用2种语言,可以发挥各自语言的特性,增加灵活性。
swig的安装可通过如下的方式:
apt-get install swig
下面来说说swig的具体使用过程:
/*example.h*/
#include <iostream>
using namespace std;
class Example
{
public:
void say_hello();
};
/*example.cpp*/
#include "example.h"
void Example::say_hello(){
cout<<"hello"<<endl;
}
/*example.i*/
%module example
%{
#include "example.h"
%}
%include "example.h"
运行下面的命令,生成包裹文件,example_wrap.cxx
swig -c++ -python example.i
生成共享库,具体的方式有distutils和g++的方式,在Python中直接通过导入库的方式调用即可。
"""
setup.py file for SWIG C\+\+/Python example
"""
from distutils.core import setup, Extension
example_module = Extension('_example',
sources=['example.cpp', 'example_wrap.cxx',],
)
setup (name = 'example',
version = '0.1',
author = "example",
description = """Simple swig C\+\+/Python example""",
ext_modules = [example_module],
py_modules = ["example"],
)
接着执行下面的命令生成共享库:
python setup.py build_ext --inplace
gcc -fPIC -I/usr/include/python2.5/ -lstdc++ -shared -o _example.so example_wrap.cxx example.cpp
注意,-fPIC和-lstdc++都是必要的。example.so前的’‘也是必要的。