python作为一种胶水和c/c++
如果需要用 Python 调用 C/C++ 编写的第三方库,只需要一个脚本语言来粘合它们。这个时候,用 Python ctypes 可以很方便地实现调用。
StackOverflow 上的 Calling C/C++ from python 这个主题介绍了 ctypes 最简单的入门方法,概括如下:
- 如果是 C 函数库,则直接 load 这个库,然后调用即可;
- 如果是 C++ 函数库,则需要用 extern 关键字封装一个供 C 使用的函数,即把类隐藏到一些 C 风格的函数里,然后用 extern 标明这些函数,以方便外部调用。
这两种方法里,弄懂了 ctypes 调用 C++ 库的方法,就会用 ctypes 调用 C 函数库,对 C++ 库的基本方法如下。
例如,有一个 C++ 类 Foo:
- #include <iostream>
- class Foo{
- public:
- void bar(){
- std::cout << "Hello" << std::endl;
- }
- };
再封装出下面 C 风格的接口函数:
- extern "C" {
- Foo* Foo_new(){
- return new Foo();
- }
- void Foo_bar(Foo* foo){
- foo->bar();
- }
- }
把上面的代码编译成动态链接库:
- g++ -c -fPIC foo.cpp -o foo.o
- g++ -shared -Wl,-soname,libfoo.so -o libfoo.so foo.o
,然后再用 Python 写的代码来调用这个类,你可以把上面两个 C 接口函数写成 Python 类,或是直接调用:
- from ctypes import cdll
- lib = cdll.LoadLibrary('./libfoo.so')
- class Foo(object):
- def __init__(self):
- self.obj = lib.Foo_new()
- def bar(self):
- lib.Foo_bar(self.obj)
,然后就可以在 Python 脚本里调用这个 Python 类了:
- f = Foo()
- f.bar() #and you will see "Hello" on the screen
在 Windows 下用 Python ctypes 的方法和上面一样,只是有下面两点需要注意一下:
- 在编写 Python 代码时,刚开始链接所需的动态链接库时,最好使用绝对路径来 load,以减少出错概率,加快调试速度
在我按上面的方法编写好了上述代码时,一运行脚本,则提示如下错误信息:
- $ python Linkcpp.py
- Traceback (most recent call last):
- File "Linkcpp.py", line 2, in <module>
- lib = cdll.LoadLibrary('./LinkExample')
- File "C:\Python27\lib\ctypes\__init__.py", line 431, in LoadLibrary
- return self._dlltype(name)
- File "C:\Python27\lib\ctypes\__init__.py", line 353, in __init__
- self._handle = _dlopen(self._name, mode)
- WindowsError: [Error 126]
这是因为我在代码里是使用了这样的代码来导入动态链接库:
- from ctypes import cdll
- lib = cdll.LoadLibrary('./LinkExample')
如果把 ./LinkExample 这句换成 Windows 下的绝对路径 E:/PythonCode/LinkCpp/LinkExample,则没有错误提示了。当然,你直接把 ./LinkExample 换成 LinkExample 也可以找到该链接库。
所以,刚开始的时候,使用绝对路径,以确保你不会纠结于能不能找到链接库之类的问题。
在运行上述脚本的时候,出现 WindowsError: [Error 126] 的错误,无非就是两个原因:
- 你的 DLL 没有正确地被加载;
- 你的 DLL 依赖的其它 DLL 没有被找到或是加载失败。
另外,注意一下,Windows 下因为库分为 lib 和 dll 两个文件,所以可以只输入库的名称即可,比如说你要链接 LinkExample.dll 库,则可以在 ctypes 里只需要声明链接名为 LinkExample 库即可。
- $ python Linkcpp.py
- 如果是 C++ 写的库,需要用上 extern 关键字,这个和一般的供 C 调用的 C++ 库头文件是一样的
在 extern 声明的函数里,可以使用 C++ 里 C 没有的关键字,比如我的函数就是这样声明的:
- externint linkExample(constint index, constchar* name);
上面代码可以从 Python 调用运行。
extern:extern可置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量或函数时,在其它模块中寻找其定义。另外,extern也可用来进行链接指定。
亲自实现
c++
g++编译 g++ -o libpycallclass.so -shared -fPIC ex.cpp
- #include <iostream>
- using namespace std;
- class TestLib
- {
- public:
- void display();
- void display(int a);
- };
- void TestLib::display() {
- cout<<"First display"<<endl;
- }
- void TestLib::display(int a) {
- cout<<"Second display:"<<a<<endl;
- }
- extern "C" {
- TestLib obj;
- void display() {
- obj.display();
- }
- void display_int() {
- obj.display();
- }
- }
- #include <iostream>
python 调用
- import ctypes
- so = ctypes.cdll.LoadLibrary
- lib = so("./libpycallclass.so")
- print 'display()'
- lib.display()
- print 'display(100)'
- lib.display_int(100)
参考资料:
stackoverflow.com calling-c-c-from-python
python调用c/c++相关工具:Boost.python
二次转发:http://blog.csdn.net/suwei19870312/article/details/18181675
python作为一种胶水和c/c++的更多相关文章
- 学习Python的三种境界
前言 王国维在<人间词话>中将读书分为了三种境界:"古今之成大事业.大学问者,必经过三种之境界:'昨夜西风凋碧树,独上高楼,望尽天涯路'.此第一境也.'衣带渐宽终不悔,为伊消得人 ...
- 从python run 和python unittest两种eclipse运行方式深入理解if __name__ == "__main__"
在写一个简单的python测试程序的时候,发现eclipse中Run as "Python run 和 Python unittest”结果不一样?为什么会不一样? 先贴一下代码段: # - ...
- Python面试题之python是一种什么语言及优缺点
1.说说python是一种什么语言? 参考答案:python是一门动态解释性的强类型定义语言 编译型vs解释型 编译型优点:编译器一般会有预编译的过程对代码进行优化.因为编译只做一次,运行时不需要编译 ...
- [译]Python作为一种编程语言有多强大?
Quora上有个问题:Python作为一种编程语言有多强大? 以下是Patrycja Okowicka的回答 说实话,Python是一门强大的语言,几乎所有东西都可以用Python创建!这就是为什么它 ...
- 从Scratch到Python——python turtle 一种比pygame更加简洁的实现
从Scratch到Python--python turtle 一种比pygame更加简洁的实现 现在很多学校都开设了Scratch课程,学生可以利用Scratch创作丰富的作品,然而Scratch之后 ...
- python selenium 三种等待方式详解[转]
python selenium 三种等待方式详解 引言: 当你觉得你的定位没有问题,但是却直接报了元素不可见,那你就可以考虑是不是因为程序运行太快或者页面加载太慢造成了元素不可见,那就必须要加等待 ...
- python的6种基本数据类型--字典
python的6种基本数据类型--字典 字典 字典的定义与特性 字典是Python语言中唯一的映射类型. 定义:{key1:value1,key2:value2} 1.键与值用冒号":& ...
- Python的三种格式化输出
今天刚学了python的三种格式化输出,以前没接触过这么有趣的输出方式,现在来分享一下. #!/user/bin/env python#coding:utf-8#三种格式化输出 #第一种格式化输出na ...
- 转载:帮你提升 Python 的 27 种编程语言
帮你提升 Python 的 27 种编程语言: 出处:http://www.oschina.net/translate/languages-to-improve-your-python
随机推荐
- android 关于appcompat v7出错问题与解决
1.appcompat_v7:应用兼容包,V7说的是版本7,即android2.1,这个兼容包支持2.1版本以上系统2.最近谷歌官方将兼容jar包与某些资源文件单独拿出来建立了一个android工程, ...
- Android开发中的Json字符串与复杂的嵌套对象互转。
Gson 可能是大家都觉得比较简单吧.我发现用JSONObject和网上下载的JSONHelper类使用起来很无语,只能解析简单的单层对象,如果有嵌套的就不能直转转成可用对象了.所以网上找了一会儿,发 ...
- Spark standlone安装与配置
spark的安装简单,去官网下载与集群hadoop版本相一致的文件即可. 解压后,主要需要修改spark-evn.sh文件. 以spark standlone为例,配置dn1,nn2为master,使 ...
- jquery图片时钟
一.生成数字时钟 <script src="http://code.jquery.com/jquery-latest.js"></script> <s ...
- [转]六款值得推荐的android(安卓)开源框架简介
本文转自:http://www.jb51.net/article/51052.htm .volley 项目地址 https://github.com/smanikandan14/Volley-demo ...
- pyenv 使用简介
pyenv 是一个 python 版本管理工具,可以方便用户在不同的 python 版本间切换,例如我的电脑里默认的 python 是 2.6, 但我还想装 2.7 3.5 等.另有一个名为 pyen ...
- ac自动机 模板
自己写的0.0 #include <queue> #include <cstring> #include <cstdio> using namespace std; ...
- Vijos1046观光旅游[floyd 最小环]
背景 湖南师大附中成为百年名校之后,每年要接待大批的游客前来参观.学校认为大力发展旅游业,可以带来一笔可观的收入. 描述 学校里面有N个景点.两个景点之间可能直接有道路相连,用Dist[I,J]表示它 ...
- 第六章、Struts2数据校验
一.三种实现方式 ① 用validate()方法实现数据校验 继承ActionSupport类,该类实现了Validateable接口,该接口中定义了一个validate()方法,在自定义的Actio ...
- pitch yaw roll 的区别
http://blog.163.com/vipwdp@126/blog/static/150224366201281935518196/