2013-09-03 4 views
1

나는 소스 C++로 몇 가지 기능을 가지고는 다음과 같이 선언 :(리눅스)

extern "C" { 
    int32_t comp_ip_long(const std::vector<EachColumn>& in, std::vector<EachColumn>& out); 
} 
는 C++ 코드는 xxx.so (리눅스 공유 객체)로 컴파일 내가 전화를 걸됩니다

파이썬에서의 함수. 내가 C++ 코드를 수정할 수 없다는 것을 알아두면, boost::python 같은 것을 액세스 할 수 없다.

나는 ctypes.CDLL을 시도했지만 xxx.so에 복잡한 인수를 전달하는 방법을 모른다.

PS :

I 일부 기능을 가진 .so는 준 (상기 파라미터 타입이 있지만, 기능을 모르는)의 함수 이름 및 파라미터들은 사용자에 의해 입력된다.

답변

1

나는 std::vector<EachColumn>을 생성 (초기화)하고 채우기 위해 extern "C"으로 선언 된 헬퍼 글루 함수가 필요하며 파이썬에서 이러한 헬퍼 함수를 ​​호출해야한다고 생각합니다.

아마도

typedef std::vector<EachColumn> columnvect_t; 
extern "C" columnvect_t *new_vect() 
    { return new columnvect_t; }; 
extern "C" void del_vect(columnvect_t*vec) 
    { delete vec; }; 
extern "C" void pushback_vect(columnvect_t* vec, EachColumn* col) 
    { vec->push_back(*col); }; 

마찬가지로 당신의 EachColumn 클래스

.

은 어쩌면 당신은

기본적으로 파이썬 -ed는 C++ 라이브러리와 dlopen에 연결된 접착제 라이브러리를 만들 필요가, 파이썬 친화적 (그래서 당신은 C++ 글루 코드 같은 느낌 만들 필요가 C++보다 C 친절 C for Python). 어떤 C++ 예외 던지고 파이썬 인터프리터 (그래서 당신의 접착제 기능을 내부에 그들 모두를 잡을 수)

C 또는 C++의 코드가 큰 경우, 당신도 아마 같은 연결 코드를 생성하기 위해 GCC를 사용자 정의하는 것이 좋습니다 교차하지 않도록주의 MELT 또는 D.Malcom의 GCC python Plugin. 그러나 이것은 시간이 걸립니다.

+0

C++ 코드를 추가해야합니다. 사실 함수 이름은 다른 사람들에 의해 제공되며 나는 전혀 모른다. – richselian

1

ctypes에서 호출 할 수 없기 때문에 C에서 함수를 왜곡해야 Python에서 호출 할 수 있습니다.

나는 함수의 세부 사항을 모르지만 예를 들어, 당신은 ++ 코드 등이 C가있는 경우 : 지금

// previous code here + 
#define CAST_FOO(x) (static_cast<Foo *>(x)) 

#ifndef FOO_DEBUG 
extern "C" { 
#endif 

void* foo_new(int bar) { 
    return static_cast<void*>(new Foo(bar)); 
} 

int foo_get_bar(void *foo) { 
    return CAST_FOO(foo)->getBar(); 
} 

void foo_set_bar(void *foo, int bar) { 
    CAST_FOO(foo)->setBar(bar); 
} 
void foo_do_something(void* foo) { 
    CAST_FOO(foo)->doSomething(); 
} 

void foo_destroy(void* foo) { 
    delete CAST_FOO(foo); 
} 

#ifndef FOO_DEBUG 
}; 
#endif 

#ifdef FOO_DEBUG 
int main(int argc, char **argv) { 
    void* foo = foo_new(10); 

    foo_do_something(foo); 
    foo_set_bar(foo, 20); 
    foo_do_something(foo); 

    foo_destroy(foo); 

    return 0; 
} 
#endif 

가 있어야한다 :

#include <iostream> 

class Foo { 
    int bar; 
public: 
    Foo(int bar) : bar(bar) {} 

    int getBar() const { 
    return bar; 
    } 

    void setBar(int bar) { 
    this->bar = bar; 
    } 

    void doSomething() const { 
    std::cout << bar << std::endl; 
    } 
}; 

당신이 이런 식으로하는 int 워프 수 있습니다 ctypes에서 호출 가능하며 C에서도 호출 가능합니다. 의는 "안녕하세요 시작하자,

C/C++ 전통에 따라 :

$ g++ -Wall foo.cpp -DFOO_DEBUG 
$ ./a.out 
10 
20 
$ g++ -Wall foo.cpp -shared -o foo.so 
$ python 
>>> from ctypes import * 
>>> 
>>> so = cdll.LoadLibrary('foo.so') 
>>> foo = so.foo_new(10) 
>>> 
>>> so.foo_do_something(foo) 
10 
>>> so.foo_set_bar(foo, 20) 
>>> so.foo_do_something(foo) 
20 
>>> so.foo_destroy(foo) 
>>> 
0

약간 더 많은 작업하지만, 장기적으로 그것은 어쩌면 가치는 부스트 문서에서 가져온 Boost.Python

예를 사용하는 것입니다 , 세계 ". A C++ 함수 :

char const* greet() 
{ 
    return "hello, world"; 
} 

부스트를 작성하여 Python에 노출 될 수 있습니다.Python wrapper :

#include <boost/python.hpp> 

BOOST_PYTHON_MODULE(hello_ext) 
{ 
    using namespace boost::python; 
    def("greet", greet); 
} 

그게 전부입니다. 다 끝났어. 이제 이것을 공유 라이브러리로 만들 수 있습니다. 결과 DLL은 이제 Python에서 볼 수 있습니다. 다음은 Python 세션의 예입니다.

>>> import hello_ext 
>>> print hello_ext.greet() 
hello, world