簡體   English   中英

將多個C ++類包裝到一個Python類中

[英]Wrapping multiple C++ classes into one Python class

Cython允許通過包裝C和C ++庫的函數和類來使用它們。 我想使用的兩個庫是SFML和Box2D。 他們定義了單獨的Vector2類。 是否可以為這兩個庫(甚至可能更多)編寫一個Vector2 Python包裝器? 我的目標是在與不同的庫進行交互時使用單一Python類型的Vector2。

有人已經做過類似的事情嗎? 這將簡化事情並統一我的Python API。 我已經包裝了SFML的一部分,但除此之外,我對Cython還是陌生的。

對於參考, SFML的Vector2看起來像這樣:

template <typename T> class Vector2 {
    public:
        T x;
        T y;
        Vector2();
        Vector2(T X, T Y);
        template <typename U> explicit Vector2(const Vector2<U>& vector);
        ...
};

Box2D向量

struct b2Vec2 {
    float32 x, y;
    b2Vec2() {}
    b2Vec2(float32 xIn, float32 yIn);
    ...
};

總覽

總體思路是三個步驟:

  1. 為您的類型編寫聲明
  2. 使用相同的界面分別包裝每個類
  3. 編寫廣義向量包裝器

聲明書

首先,您需要一個包裝類型的Cython聲明。 一個示例(非常少)如下。

# This is the Cython interface for Vector2

cdef float float32 

cdef extern from "Vector2.hpp" nogil:
    # if this was an stl vector, use vector[T, ALLOCATOR=*]
    # you must list every template type, even one with default values
    cdef cppclass Vector2[T]:   
        ctypedef T value_type

        # Add all the overloads, for example, multiplication
        Vector2[T, ALLOCATOR] operator*(const T&) const;


cdef extern from "b2Math.h" nogil:
    cdef cppclass b2Vec2:

        # Add all overloads, for example, multiplication
        void operator*=(float)

接口

接下來,您需要將它們包裝到Python包裝器中。 您需要確保它們具有相同的接口,以便一個可以像另一個一樣使用。 Python數據模型是您的朋友。 一個非常簡單的示例是:

cdef class SfmlVector2_32:
    # This is a definition for a float32 vector from Sfml
    Vector2[float32] c

    def __mul__(self, float32 x):
        # multiple and assign
        B2Vector2_32 copy;
        copy.c = c * x
        return copy;

cdef class B2Vector2_32:
    # This is a definition for a float32 vector from box2
    b2Vec2 c

    def __mul__(self, float32 x):
        # multiple and assign
        B2Vector2_32 copy;
        copy.c = c;
        copy.c *= x
        return copy

廣義向量

最后,您需要一個簡單的包裝器類,該包裝器綁定許多向量類型之一並對該類執行正確的操作。 由於Python不是靜態類型的,並且包裝的每個向量的接口都是相同的,因此這很容易:只需在__init__初始化正確的向量即可。

class Vector2_32:

    def __init__(self, framework = 'SFML'):
        # ideally, perform a dictionary lookup if you have many classes
        # O(1) for dict, if/then is O(n)
        if framework == 'SFML':
            self.vector = SfmlVector2_32()
        elif framework == 'BOX2':
            self.vector = B2Vector2_32()
        else:
            raise TypeError("Unrecognized framework.")

    def __mul__(self, float32 x):
        Vector2_32 copy
        copy.vector = vector * x
        return copy

思想

這是一個非常糟糕的示例,因為通常情況下,您是根據__imul__ (就地乘法)實現__mul__ __imul__ (乘法)的,但是卻能使您大致理解。 這段代碼中可能有錯別字,我現在無法訪問機器進行編譯。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM