파이썬에서 C / C ++를 호출합니까?
C 또는 C ++ 라이브러리에 파이썬 바인딩을 구성하는 가장 빠른 방법은 무엇입니까?
(중요한 경우 Windows를 사용하고 있습니다.)
Boost.Python을 살펴 봐야 합니다. 그들의 웹 사이트에서 가져온 짧은 소개는 다음과 같습니다.
Boost Python Library는 Python과 C ++를 인터페이스하기위한 프레임 워크입니다. C ++ 컴파일러만으로도 특별한 툴을 사용하지 않고도 C ++ 클래스 함수와 객체를 파이썬에 빠르고 완벽하게 노출시킬 수 있습니다. C ++ 인터페이스를 방해하지 않고 감싸도록 설계되었으므로 C ++ 코드를 변경하기 위해 전혀 변경하지 않아도되므로 Boost.Python은 타사 라이브러리를 Python에 노출시키는 데 이상적입니다. 라이브러리에서 고급 메타 프로그래밍 기술을 사용하면 사용자의 구문이 단순 해져 래핑 코드가 일종의 선언적 인터페이스 정의 언어 (IDL)를 살펴볼 수 있습니다.
ctypes 는 표준 라이브러리의 일부이므로 swig 보다 안정적이고 널리 사용 가능하므로 항상 문제가 발생 합니다.
ctypes를 사용하면 파이썬에 대한 컴파일 시간 종속성을 충족시켜야하며 바인딩은 ctypes가있는 모든 파이썬에서 컴파일됩니다.
foo.cpp라는 파일에서 대화하려는 간단한 C ++ 예제 클래스가 있다고 가정하십시오.
#include <iostream>
class Foo{
public:
void bar(){
std::cout << "Hello" << std::endl;
}
};
ctype은 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
그리고 마지막으로 파이썬 래퍼를 작성해야합니다 (예 : 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
가장 빠른 방법은 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);
유닉스에서 파이썬 모듈 만들기 :
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가 있어야합니다. 또한 일부 시스템에서 파이썬 헤더 파일은 설치 방법에 따라 /usr/include/python2.7에 있습니다.
튜토리얼에서 :
SWIG는 거의 모든 언어 기능을 지원하는 상당히 완전한 C ++ 컴파일러입니다. 여기에는 전처리, 포인터, 클래스, 상속 및 C ++ 템플릿이 포함됩니다. SWIG를 사용하면 구조와 클래스를 대상 언어의 프록시 클래스로 패키지하여 기본 기능을 매우 자연스럽게 노출 할 수 있습니다.
이 페이지에서 Python <-> C ++ 바인딩에 대한 여정을 시작했습니다. 높은 수준의 데이터 형식 (Python 목록과 다차원 STL 벡터)을 연결하려는 목적으로 :-)
ctypes 와 boost.python (및 소프트웨어 엔지니어 아님)을 기반으로 솔루션을 시도한 결과 높은 수준의 데이터 유형 바인딩이 필요할 때 복잡한 것으로 나타 났지만 SWIG 는 이러한 경우에 훨씬 더 간단 하다는 것을 알았습니다 .
따라서이 예에서는 SWIG를 사용하며 Linux에서 테스트되었지만 SWIG를 사용할 수 있으며 Windows에서도 널리 사용됩니다.
목표는 2D STL 벡터 형태의 행렬을 가져와 각 행의 평균을 1D STL 벡터로 반환하는 Python에서 C ++ 함수를 사용할 수있게하는 것입니다.
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
이제 파이썬 스크립트에서 함수를 사용할 수 있습니다 :
#!/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
pyrex 또는 Cython을 확인하십시오 . C / C ++와 Python 간의 인터페이스를위한 Python과 유사한 언어입니다.
또한 pybind11
가벼운 버전의 Boost.Python 과 비슷하며 모든 최신 C ++ 컴파일러와 호환됩니다.
https://pybind11.readthedocs.io/en/latest/
파이썬이 과학자가 필요로한다고 주장하는이 논문 은 기본적으로 다음과 같이 말합니다. 그런 다음 부품 속도를 높이려면 SWIG를 사용하여이 부품을 C로 변환하십시오.
최신 C ++의 경우 cppyy를 사용하십시오. http://cppyy.readthedocs.io/en/latest/
Clang / LLVM의 C ++ 인터프리터 인 Cling을 기반으로합니다. 바인딩은 런타임에 있으며 추가 중간 언어가 필요하지 않습니다. 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의 저자입니다.
나는 그것을 사용한 적이 없지만 ctypes에 대해 좋은 것을 들었습니다 . C ++에서 사용하려는 경우를 통해 name mangling을 피하십시오 extern "C"
. 의견을 주셔서 감사합니다. Florian Bösch.
나는 파이썬의 cffi가 옵션 일 수 있다고 생각합니다.
목표는 Python에서 C 코드를 호출하는 것입니다. 당신은 제 3 언어를 배우지 않고도 그렇게 할 수 있어야합니다. 모든 대안은 자신의 언어 (Cython, SWIG) 또는 API (ctypes)를 배워야합니다. 그래서 우리는 파이썬과 C를 알고 있다고 가정하고 배우는 데 필요한 추가 비트를 최소화하려고 시도했습니다.
http://cffi.readthedocs.org/en/release-0.7/
문제는 올바르게 이해하면 Python에서 C 함수를 호출하는 방법입니다. 그렇다면 가장 좋은 방법은 Ctypes입니다 (파이썬의 모든 변형에서 BTW 이식 가능).
>>> 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
공식 파이썬 문서 중 하나에는 C / C ++를 사용하여 파이썬 을 확장하는 것에 대한 세부 정보가 들어 있습니다 . SWIG를 사용하지 않아도 매우 간단하며 Windows에서 완벽하게 작동합니다.
Java 래퍼 작성을 예상하지 않는 한 Cython은 확실히 갈 길입니다.이 경우 SWIG가 더 좋습니다.
runcython
커맨드 라인 유틸리티를 사용하는 것이 좋습니다 . Cython을 사용하는 프로세스가 매우 쉽습니다. 구조화 된 데이터를 C ++로 전달해야하는 경우 Google의 프로토 타입 라이브러리를 살펴보면 매우 편리합니다.
다음은 두 도구를 모두 사용하는 최소 예제입니다.
https://github.com/nicodjimenez/python2cpp
그것이 유용한 출발점이 될 수 있기를 바랍니다.
먼저 특정 목적이 무엇인지 결정해야합니다. 파이썬 인터프리터 확장 및 임베드 에 대한 공식 파이썬 문서 는 위에서 언급 했으므로 바이너리 확장에 대한 좋은 개요를 추가 할 수 있습니다 . 사용 사례는 3 가지 범주로 나눌 수 있습니다.
- 가속기 모듈 : CPython에서 실행되는 동등한 순수 Python 코드보다 빠르게 실행합니다.
- 래퍼 모듈 : 기존 C 인터페이스를 Python 코드에 노출합니다.
- 낮은 수준의 시스템 액세스 : CPython 런타임, 운영 체제 또는 기본 하드웨어의 낮은 수준의 기능에 액세스합니다.
다른 관심사에 대한 더 넓은 관점을 제공하고 초기 질문이 약간 모호하기 때문에 ( "C 또는 C ++ 라이브러리에 대한")이 정보가 흥미로울 것입니다. 위의 링크에서 바이너리 확장과 그 대안을 사용할 때의 단점에 대해 읽을 수 있습니다.
제안 된 다른 답변 외에도 가속기 모듈을 원한다면 Numba 을 사용해보십시오 . "가져 오기 시간, 런타임 또는 정적으로 (포함 된 pycc 도구를 사용하여) LLVM 컴파일러 인프라를 사용하여 최적화 된 기계 코드를 생성하여 작동합니다."
참고 URL : https://stackoverflow.com/questions/145270/calling-cc-from-python
'development' 카테고리의 다른 글
자르지 않고 전체 NumPy 배열을 인쇄하는 방법은 무엇입니까? (0) | 2020.02.13 |
---|---|
원숭이 패치 란 무엇입니까? (0) | 2020.02.13 |
git commit 메시지에 과거 또는 현재 시제를 사용해야합니까? (0) | 2020.02.13 |
MongoDB 또는 CouchDB-프로덕션에 적합합니까? (0) | 2020.02.13 |
HTML을 사용하여 문서의 모든 인쇄 페이지에 머리글과 바닥 글을 인쇄하는 방법은 무엇입니까? (0) | 2020.02.13 |