문제

방금 CTypes를 시작하고 CTYPES를 사용하여 Python 내에서 DLL 파일로 내보낸 C ++ 클래스를 사용하고 싶습니다. 그래서 내 C ++ 코드가 다음과 같이 보입니다.

class MyClass {
  public:
    int test();
...

이 클래스가 포함 된 .dll 파일을 작성한 다음 CTypes를 사용하여 .dll 파일을 Python에로드합니다. 이제 myclass 유형의 객체를 어떻게 만들고 테스트 기능을 호출합니까? CTypes에서도 가능합니까? 또는 SWIG 또는 BOST.PYTHON을 사용하는 것을 고려하지만 CTYPES는 소규모 프로젝트에서 가장 쉬운 옵션처럼 보입니다.

도움이 되었습니까?

해결책

짧은 이야기는 C가있는 방식으로 C ++에 대한 표준 바이너리 인터페이스가 없다는 것입니다. 이름은 엉망이되고 라이브러리 기능 호출 사이의 스택을 처리하는 다른 방법으로 인해 동일한 C ++ 동적 라이브러리에 대해 다른 컴파일러가 동일한 C ++ 동적 라이브러리에 대해 다른 바이너리를 출력합니다.

불행히도 C ++ 라이브러리에 액세스하는 휴대용 방법은 없습니다. 일반적으로. 그러나 한 번에 하나의 컴파일러의 경우 아무런 문제가 없습니다.

이 블로그 게시물 또한 이것이 현재 작동하지 않는 이유에 대한 짧은 개요가 있습니다. C ++ 0X가 나온 후에는 C ++에 대한 표준 ABI가 있습니까? 그때까지 Python의 C ++ 클래스에 액세스 할 수있는 방법이 없을 것입니다. ctypes.

다른 팁

boost.python (아마도 C ++ 클래스를 Python 클래스에 일대일 매핑 해야하는 대규모 프로젝트에 더 친근한 솔루션 일 것입니다) 외에도 C ++ 측면 A C 인터페이스에 제공 할 수 있습니다. 그것은 많은 사람들의 하나의 해결책이므로 자체 트레이드 오프를 가지고 있지만,이 기술에 익숙하지 않은 사람들의 이익을 위해 그것을 제시 할 것입니다. 전체 공개의 경우,이 접근법을 사용하면 C ++를 Python에 인터페이스하지 않고 C ++에서 C ~ Python을 인터페이스하는 것입니다. 아래에는 C ++ 컴파일러의 외부 "C"시설에 대한 일반적인 아이디어를 보여주는 요구 사항을 충족하는 예가 포함되어 있습니다.

//YourFile.cpp (compiled into a .dll or .so file)
#include <new> //For std::nothrow
//Either include a header defining your class, or define it here. 

extern "C"  //Tells the compile to use C-linkage for the next scope.
{
    //Note: The interface this linkage region needs to use C only.  
    void * CreateInstanceOfClass( void )
    {
        // Note: Inside the function body, I can use C++. 
        return new(std::nothrow) MyClass;
    }

    //Thanks Chris. 
    void DeleteInstanceOfClass (void *ptr)
    {
         delete(std::nothrow) ptr; 
    }

    int CallMemberTest(void *ptr)
    {

        // Note: A downside here is the lack of type safety. 
        // You could always internally(in the C++ library) save a reference to all 
        // pointers created of type MyClass and verify it is an element in that
        //structure. 
        //
        // Per comments with Andre, we should avoid throwing exceptions.  
        try
        {
            MyClass * ref = reinterpret_cast<MyClass *>(ptr);
            return ref->Test();
        }
        catch(...)
        {
           return -1; //assuming -1 is an error condition. 
        }
    }

} //End C linkage scope.

이 코드를 컴파일 할 수 있습니다

gcc -shared -o test.so test.cpp
#creates test.so in your current working directory.

파이썬 코드에서는 이와 같은 작업을 수행 할 수 있습니다 (2.7의 대화식 프롬프트) :

>>> from ctypes import cdll
>>> stdc=cdll.LoadLibrary("libc.so.6") # or similar to load c library
>>> stdcpp=cdll.LoadLibrary("libstdc++.so.6") # or similar to load c++ library
>>> myLib=cdll.LoadLibrary("/path/to/test.so")
>>> spam = myLib.CreateInstanceOfClass()
>>> spam
[outputs the pointer address of the element]
>>> value=CallMemberTest(spam)
[does whatever Test does to the spam reference of the object] 

나는 boost.python이 후드 아래에서 비슷한 일을하지만, 아마도 낮은 수준의 개념을 이해하는 것이 도움이 될 것입니다. C ++ 라이브러리의 기능에 액세스하려고 시도하고 일대일 매핑이 필요하지 않은 경우이 방법에 대해 더 흥분 할 것입니다.

C/C ++ 상호 작용에 대한 자세한 내용은 Sun 에서이 페이지를 확인하십시오. http://dsc.sun.com/solaris/articles/mixing.html#cpp_from_c

그만큼 Audaaero의 답변 매우 좋지만 완전하지는 않습니다 (적어도 나에게는).

내 시스템 (GCC 및 G ++ 6.3.0, Python 3.5.3의 Debian 스트레치 x64)에서 나는 조만간 segfaults를 가지고 있습니다. 회원 값에 액세스하십시오 수업의. 포인터 값을 STDOUT에 인쇄하여 진단하여 랩퍼의 64 비트로 코딩 된 공허* 포인터가 파이썬에서 32 비트로 표현되고 있다고 진단했습니다. 따라서 큰 문제는 멤버 기능 래퍼로 다시 전달 될 때 발생합니다.

내가 찾은 해결책은 변경하는 것입니다.

spam = myLib.CreateInstanceOfClass()

안으로

Class_ctor_wrapper = myLib.CreateInstanceOfClass
Class_ctor_wrapper.restype = c_void_p
spam = c_void_p(Class_ctor_wrapper())

그래서 두 가지가 누락되었습니다 : 반환 유형을 c_void_p로 설정합니다 (기본값은 int) 그리고 그런 다음 c_void_p 객체를 만듭니다 (정수뿐만 아니라).

나는 의견을 쓸 수 있었으면 좋겠지 만 여전히 27 개의 반복 포인트가 부족합니다.

이것은 Python의 C_Types와 함께 C 및 C ++를 사용하는 방법에 대한 간단한 설명입니다.Python 용 C ++에서 DLL/SO를 작성하는 방법

확장 Audaaero 's 그리고 가브리엘 데빌 러스 답은 다음과 같이 클래스 객체 인스턴스 생성을 완료합니다.stdc=c_void_p(cdll.LoadLibrary("libc.so.6"))사용 ctypes c_void_p 데이터 유형은 Python 내에서 클래스 객체 포인터의 올바른 표현을 보장합니다.

또한 DLL의 메모리 관리를 DLL에 의해 처리해야합니다 (DLL에 할당 된 메모리는 Python이 아닌 DLL에서도 거래해야합니다)!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top