Cython允许通过包装其函数和类来使用C和C ++库。我想使用的两个库是SFML和Box2D。它们定义了单独的Vector2类。是否可以为这两个库(可能更多)编写一个Vector2 Python包装器?我的目标是在与不同的库交互时使用单一Python类型的Vector2。
有人做过类似的事吗?这将简化事情并统一我的Python API。我已经包装了SFML的部分内容,但除此之外我还不熟悉Cython。
参考SFML's 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);
...
};
struct b2Vec2 {
float32 x, y;
b2Vec2() {}
b2Vec2(float32 xIn, float32 yIn);
...
};
答案 0 :(得分:1)
<强>概述强>
一般的想法是三个步骤:
<强>声明强>
首先,您需要为包装类型提供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 data model是你的朋友。一个非常简单的例子是:
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
<强>思想强>
这是一个非常糟糕的例子,因为通常你会根据__mul__
(就地乘法)实现__imul__
(乘法),但它会得到一般的想法。此代码中可能存在拼写错误,我现在无法访问计算机进行编译。