我读了很棒的Tutorial of Using C libraries并修改了代码,以便template <typename T=float>
class XVector3
{
public:
typedef T value_type;
__host__ __device__ inline XVector3() : x(0.0f), y(0.0f), z(0.0f) {}
__host__ __device__ inline XVector3(T a) : x(a), y(a), z(a) {}
__host__ __device__ inline XVector3(const T* p) : x(p[0]), y(p[1]), z(p[2]) {}
__host__ __device__ inline XVector3(T x_, T y_, T z_) : x(x_), y(y_), z(z_)
{
VEC3_VALIDATE();
}
__host__ __device__ inline operator T* () { return &x; }
__host__ __device__ inline operator const T* () const { return &x; };
__host__ __device__ inline void Set(T x_, T y_, T z_) { VEC3_VALIDATE(); x = x_; y = y_; z = z_;}
__host__ __device__ inline XVector3<T> operator * (T scale) const { XVector3<T> r(*this); r *= scale; return r; VEC3_VALIDATE();}
__host__ __device__ inline XVector3<T> operator / (T scale) const { XVector3<T> r(*this); r /= scale; return r; VEC3_VALIDATE();}
__host__ __device__ inline XVector3<T> operator + (const XVector3<T>& v) const { XVector3<T> r(*this); r += v; return r; VEC3_VALIDATE();}
__host__ __device__ inline XVector3<T> operator - (const XVector3<T>& v) const { XVector3<T> r(*this); r -= v; return r; VEC3_VALIDATE();}
__host__ __device__ inline XVector3<T> operator /(const XVector3<T>& v) const { XVector3<T> r(*this); r /= v; return r; VEC3_VALIDATE();}
__host__ __device__ inline XVector3<T> operator *(const XVector3<T>& v) const { XVector3<T> r(*this); r *= v; return r; VEC3_VALIDATE();}
__host__ __device__ inline XVector3<T>& operator *=(T scale) {x *= scale; y *= scale; z*= scale; VEC3_VALIDATE(); return *this;}
__host__ __device__ inline XVector3<T>& operator /=(T scale) {T s(1.0f/scale); x *= s; y *= s; z *= s; VEC3_VALIDATE(); return *this;}
__host__ __device__ inline XVector3<T>& operator +=(const XVector3<T>& v) {x += v.x; y += v.y; z += v.z; VEC3_VALIDATE(); return *this;}
__host__ __device__ inline XVector3<T>& operator -=(const XVector3<T>& v) {x -= v.x; y -= v.y; z -= v.z; VEC3_VALIDATE(); return *this;}
__host__ __device__ inline XVector3<T>& operator /=(const XVector3<T>& v) {x /= v.x; y /= v.y; z /= v.z; VEC3_VALIDATE(); return *this; }
__host__ __device__ inline XVector3<T>& operator *=(const XVector3<T>& v) {x *= v.x; y *= v.y; z *= v.z; VEC3_VALIDATE(); return *this; }
__host__ __device__ inline bool operator != (const XVector3<T>& v) const { return (x != v.x || y != v.y || z != v.z); }
// negate
__host__ __device__ inline XVector3<T> operator -() const { VEC3_VALIDATE(); return XVector3<T>(-x, -y, -z); }
__host__ __device__ void Validate()
{
VEC3_VALIDATE();
}
T x,y,z;
};
typedef XVector3<float> Vec3;
typedef XVector3<float> Vector3;
// lhs scalar scale
template <typename T>
__host__ __device__ XVector3<T> operator *(T lhs, const XVector3<T>& rhs)
{
XVector3<T> r(rhs);
r *= lhs;
return r;
}
template <typename T>
__host__ __device__ bool operator==(const XVector3<T>& lhs, const XVector3<T>& rhs)
{
return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z);
}
可以存储任何类型的数据,这是教程中的代码
Queue
然后我修改了# queue.pyx
# distutils: sources = c-algorithms/src/queue.c
# distutils: include_dirs = c-algorithms/src/
cimport cqueue
cdef class Queue:
"""A queue class for C integer values.
>>> q = Queue()
>>> q.append(5)
>>> q.peek()
5
>>> q.pop()
5
"""
cdef cqueue.Queue* _c_queue
def __cinit__(self):
self._c_queue = cqueue.queue_new()
if self._c_queue is NULL:
raise MemoryError()
def __dealloc__(self):
if self._c_queue is not NULL:
cqueue.queue_free(self._c_queue)
cpdef append(self, int value):
if not cqueue.queue_push_tail(self._c_queue,
<void*> value):
raise MemoryError()
# The `cpdef` feature is obviously not available for the original "extend()"
# method, as the method signature is incompatible with Python argument
# types (Python does not have pointers). However, we can rename
# the C-ish "extend()" method to e.g. "extend_ints()", and write
# a new "extend()" method that provides a suitable Python interface by
# accepting an arbitrary Python iterable.
cpdef extend(self, values):
for value in values:
self.append(value)
cdef extend_ints(self, int* values, size_t count):
cdef int value
for value in values[:count]: # Slicing pointer to limit the iteration boundaries.
self.append(value)
cpdef int peek(self) except? -1:
cdef int value = <Py_ssize_t> cqueue.queue_peek_head(self._c_queue)
if value == 0:
# this may mean that the queue is empty,
# or that it happens to contain a 0 value
if cqueue.queue_is_empty(self._c_queue):
raise IndexError("Queue is empty")
return value
cpdef int pop(self) except? -1:
if cqueue.queue_is_empty(self._c_queue):
raise IndexError("Queue is empty")
return <Py_ssize_t> cqueue.queue_pop_head(self._c_queue)
def __bool__(self):
return not cqueue.queue_is_empty(self._c_queue)
queue.pyx
但是当使用# queue.pyx
# distutils: sources = c-algorithms/src/queue.c
# distutils: include_dirs = c-algorithms/src/
from cpython.ref cimport PyObject
cimport cqueue
cdef class Queue:
"""A queue class for C integer values.
>>> q = Queue()
>>> q.append(5)
>>> q.peek()
5
>>> q.pop()
5
"""
cdef cqueue.Queue* _c_queue
def __cinit__(self):
self._c_queue = cqueue.queue_new()
if self._c_queue is NULL:
raise MemoryError()
def __dealloc__(self):
if self._c_queue is not NULL:
cqueue.queue_free(self._c_queue)
cdef append(self, void* value):
if not cqueue.queue_push_tail(self._c_queue,
<void*> value):
raise MemoryError()
# The `cpdef` feature is obviously not available for the original "extend()"
# method, as the method signature is incompatible with Python argument
# types (Python does not have pointers). However, we can rename
# the C-ish "extend()" method to e.g. "extend_ints()", and write
# a new "extend()" method that provides a suitable Python interface by
# accepting an arbitrary Python iterable.
cpdef extend(self, values):
cdef void * ptr;
for value in values:
ptr = <void*>value
self.append(ptr)
cpdef extend_ints(self, int* values, size_t count):
cdef PyObject* ptr
for value in values[:count]: # Slicing pointer to limit the iteration boundaries.
ptr = <PyObject*> value
self.append(ptr)
def __bool__(self):
return not cqueue.queue_is_empty(self._c_queue)
进行构建时,它会报告
python3.6 setup.py build_ext -i
如何修复代码和修改功能Compiling queue.pyx because it changed.
[1/1] Cythonizing queue.pyx
Error compiling Cython file:
------------------------------------------------------------
...
cdef void * ptr;
for value in values:
ptr = <void*>value
self.append(ptr)
cpdef extend_ints(self, int* values, size_t count):
^
------------------------------------------------------------
queue.pyx:45:10: Cannot convert 'int *' to Python object
Traceback (most recent call last):
File "setup.py", line 6, in <module>
ext_modules = cythonize([Extension("queue", ["queue.pyx"])])
File "/Users/me/Library/Python/3.6/lib/python/site-packages/Cython/Build/Dependencies.py", line 1026, in cythonize
cythonize_one(*args)
File "/Users/me/Library/Python/3.6/lib/python/site-packages/Cython/Build/Dependencies.py", line 1146, in cythonize_one
raise CompileError(None, pyx_file)
Cython.Compiler.Errors.CompileError: queue.pyx
和peek
的代码?