(如果这很重要,我正在使用Windows。)
#1楼
最快的方法是使用SWIG 。
来自SWIG 教程的示例 :
/* File : example.c */
int fact(int n) {
if (n <= 1) return 1;
else return n*fact(n-1);
}
接口文件:
/* example.i */
%module example
%{
/* Put header files here or function declarations like below */
extern int fact(int n);
%}
extern int fact(int n);
在Unix上构建Python模块:
swig -python example.i
gcc -fPIC -c example.c example_wrap.c -I/usr/local/include/python2.7
gcc -shared example.o example_wrap.o -o _example.so
用法:
>>> import example
>>> example.fact(5)
120
请注意,您必须具有python-dev。 同样在某些系统中,python头文件会根据您的安装方式位于/usr/include/python2.7中。
从教程中:
SWIG是一个相当完整的C ++编译器,几乎支持所有语言功能。 这包括预处理,指针,类,继承,甚至C ++模板。 SWIG还可以用于以目标语言将结构和类打包到代理类中-以非常自然的方式公开基础功能。
#2楼
我从未使用过它,但是我听说过有关ctypes的好东西。 如果您尝试将其与C ++一起使用,请确保通过extern "C"
逃避名称处理。 感谢弗洛里安·博斯(FlorianBösch)的评论。
#3楼
本文声称Python是科学家的全部需要 ,基本上说:首先用Python制作一切原型。 然后,当您需要加快零件速度时,请使用SWIG并将其转换为C。
#4楼
一份正式的Python文档包含有关使用C / C ++扩展Python的详细信息。 即使不使用SWIG ,它也非常简单,并且在Windows上也能很好地工作。
#5楼
检查出pyrex或Cython 。 它们是类似于Python的语言,用于C / C ++和Python之间的接口。
#6楼
您应该看看Boost.Python 。 以下是他们网站上的简短介绍:
Boost Python库是用于连接Python和C ++的框架。 它使您无需使用特殊工具(仅使用C ++编译器)即可快速,无缝地向Python展示C ++类的函数和对象,反之亦然。 它被设计为以非侵入方式包装C ++接口,因此您不必为了包装而完全更改C ++代码,从而使Boost.Python成为将第三方库公开给Python的理想选择。 该库对高级元编程技术的使用为用户简化了其语法,因此包装代码具有一种声明性接口定义语言(IDL)的外观。
#7楼
ctypes是标准库的一部分,因此比swig更稳定和更易于使用,后者经常会给我带来麻烦 。
使用ctypes时,您需要满足对python的任何编译时依赖性,并且绑定将对任何具有ctypes的python起作用,而不仅仅是针对ctypes的python。
假设您要在一个名为foo.cpp的文件中讨论一个简单的C ++示例类:
#include <iostream>
class Foo{
public:
void bar(){
std::cout << "Hello" << std::endl;
}
};
由于ctypes只能与C函数对话,因此您需要提供将其声明为extern“ 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包装器(例如,在fooWrapper.py中)
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)
一旦有了,您可以像这样称呼它
f = Foo()
f.bar() #and you will see "Hello" on the screen
#8楼
我认为cffi for python是一个选择。
目的是从Python调用C代码。 您应该能够在不学习第三语言的情况下进行操作:每种选择都要求您学习自己的语言(Cython,SWIG)或API(ctypes)。 因此,我们尝试假设您了解Python和C,并尽量减少了您需要学习的API附加位。
http://cffi.readthedocs.org/en/release-0.7/
#9楼
我从此页面的Python <-> C ++绑定开始了我的旅程,目的是链接高级数据类型(带有Python列表的多维STL向量):-)
尝试过基于ctypes和boost.python的解决方案(并且不是软件工程师),当需要高级数据类型绑定时,我发现它们很复杂,而对于这种情况,我发现SWIG更加简单。
因此,该示例使用了SWIG,并且已经在Linux中进行了测试(但是SWIG可用,并且在Windows中也被广泛使用)。
目的是使C ++函数可用于Python,该函数采用2D STL向量形式的矩阵并返回每一行的平均值(作为1D STL向量)。
C ++中的代码(“ code.cpp”)如下:
#include <vector>
#include "code.h"
using namespace std;
vector<double> average (vector< vector<double> > i_matrix) {
// Compute average of each row..
vector <double> averages;
for (int r = 0; r < i_matrix.size(); r++){
double rsum = 0.0;
double ncols= i_matrix[r].size();
for (int c = 0; c< i_matrix[r].size(); c++){
rsum += i_matrix[r][c];
}
averages.push_back(rsum/ncols);
}
return averages;
}
等效的标头(“ code.h”)为:
#ifndef _code
#define _code
#include <vector>
std::vector<double> average (std::vector< std::vector<double> > i_matrix);
#endif
我们首先编译C ++代码以创建目标文件:
g++ -c -fPIC code.cpp
然后,我们为C ++函数定义一个SWIG接口定义文件 (“ code.i”)。
%module code
%{
#include "code.h"
%}
%include "std_vector.i"
namespace std {
/* On a side note, the names VecDouble and VecVecdouble can be changed, but the order of first the inner vector matters! */
%template(VecDouble) vector<double>;
%template(VecVecdouble) vector< vector<double> >;
}
%include "code.h"
使用SWIG,我们从SWIG接口定义文件生成C ++接口源代码。
swig -c++ -python code.i
最后,我们编译生成的C ++接口源文件,并将所有内容链接在一起,以生成可由Python直接导入的共享库(“ _”很重要):
g++ -c -fPIC code_wrap.cxx -I/usr/include/python2.7 -I/usr/lib/python2.7
g++ -shared -Wl,-soname,_code.so -o _code.so code.o code_wrap.o
现在,我们可以在Python脚本中使用该函数:
#!/usr/bin/env python
import code
a= [[3,5,7],[8,10,12]]
print a
b = code.average(a)
print "Assignment done"
print a
print b
#10楼
首先,您应该确定自己的特定目的。 上面提到了有关扩展和嵌入Python解释器的官方Python文档,我可以添加一个很好的二进制扩展概述 。 用例可分为3类:
- 加速器模块 :运行速度比CPython中运行的等效纯Python代码更快。
- 包装模块 :将现有的C接口公开给Python代码。
- 低级系统访问 :访问CPython运行时,操作系统或底层硬件的低级功能。
为了给其他感兴趣的人一个更广阔的视野,并且由于您的最初问题有点含糊(“对C或C ++库”),我想您可能会对这些信息感兴趣。 在上面的链接上,您可以了解使用二进制扩展名及其替代方法的缺点。
除了建议的其他答案外,如果您需要加速器模块,还可以尝试Numba 。 它的工作原理是“通过在导入时,运行时或静态(使用附带的pycc工具)使用LLVM编译器基础结构生成优化的机器代码”。
#11楼
问题是,如果我理解正确的话,如何从Python调用C函数。 然后最好的选择是Ctypes(BTW可在所有Python变体中移植)。
>>> from ctypes import *
>>> libc = cdll.msvcrt
>>> print libc.time(None)
1438069008
>>> printf = libc.printf
>>> printf("Hello, %s\n", "World!")
Hello, World!
14
>>> printf("%d bottles of beer\n", 42)
42 bottles of beer
19
有关详细指南,您可能需要参考我的博客文章 。
#12楼
除非您期望编写Java包装程序,否则Cython绝对是必经之路,在这种情况下,SWIG可能更可取。
我建议使用runcython
命令行实用程序,它使使用Cython的过程非常容易。 如果您需要将结构化数据传递给C ++,请查看Google的protobuf库,它非常方便。
这是我使用这两种工具的最小示例:
https://github.com/nicodjimenez/python2cpp
希望它可以是一个有用的起点。
#13楼
还有pybind11
,它像Boost.Python的轻量级版本,并且与所有现代C ++编译器兼容:
https://pybind11.readthedocs.io/en/latest/
#14楼
对于现代C ++,请使用cppyy: http ://cppyy.readthedocs.io/en/latest/
它基于Cling / Clang / LLVM的C ++解释器。 绑定是在运行时执行的,不需要其他中间语言。 感谢Clang,它支持C ++ 17。
使用pip安装它:
$ pip install cppyy
对于小型项目,只需加载相关的库和您感兴趣的标头。例如,从ctypes示例中获取代码就是该线程,但分为标头和代码部分:
$ cat foo.h
class Foo {
public:
void bar();
};
$ cat foo.cpp
#include "foo.h"
#include <iostream>
void Foo::bar() { std::cout << "Hello" << std::endl; }
编译:
$ g++ -c -fPIC foo.cpp -o foo.o
$ g++ -shared -Wl,-soname,libfoo.so -o libfoo.so foo.o
并使用它:
$ python
>>> import cppyy
>>> cppyy.include("foo.h")
>>> cppyy.load_library("foo")
>>> from cppyy.gbl import Foo
>>> f = Foo()
>>> f.bar()
Hello
>>>
大型项目通过自动加载准备的反射信息和cmake片段来创建它们而受支持,因此安装包的用户可以简单地运行:
$ python
>>> import cppyy
>>> f = cppyy.gbl.Foo()
>>> f.bar()
Hello
>>>
多亏了LLVM,高级功能才得以实现,例如自动模板实例化。 继续示例:
>>> v = cppyy.gbl.std.vector[cppyy.gbl.Foo]()
>>> v.push_back(f)
>>> len(v)
1
>>> v[0].bar()
Hello
>>>
注意:我是cppyy的作者。
#15楼
您可以使用Scapix语言桥直接从C ++标头自动生成Python绑定,作为构建的一部分。
scapix_bridge_headers()
的调用添加到CMakeLists.txt文件,然后使用cmake -DSCAPIX_BRIDGE=python
构建项目。 查看完整示例 。
免责声明:我是Scapix Language Bridge的作者。
p15097962069 发布了0 篇原创文章 · 获赞 1 · 访问量 3849 私信 关注