mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 00:32:57 -04:00
express: fix PTA get_data in Python 3, fix CPTA construction
Fixes: #173
This commit is contained in:
parent
5ac3ccb6f6
commit
dfa47e55ce
@ -105,9 +105,9 @@ PUBLISHED:
|
||||
INLINE void set_element(size_type n, const Element &value);
|
||||
EXTENSION(const Element &__getitem__(size_type n) const);
|
||||
EXTENSION(void __setitem__(size_type n, const Element &value));
|
||||
INLINE string get_data() const;
|
||||
INLINE void set_data(const string &data);
|
||||
INLINE string get_subdata(size_type n, size_type count) const;
|
||||
EXTENSION(PyObject *get_data() const);
|
||||
EXTENSION(void set_data(PyObject *data));
|
||||
EXTENSION(PyObject *get_subdata(size_type n, size_type count) const);
|
||||
INLINE void set_subdata(size_type n, size_type count, const string &data);
|
||||
INLINE int get_ref_count() const;
|
||||
INLINE int get_node_ref_count() const;
|
||||
@ -255,14 +255,12 @@ PUBLISHED:
|
||||
INLINE ConstPointerToArray(const PointerToArray<Element> ©);
|
||||
INLINE ConstPointerToArray(const ConstPointerToArray<Element> ©);
|
||||
|
||||
EXTENSION(ConstPointerToArray(PyObject *self, PyObject *source));
|
||||
|
||||
typedef TYPENAME pvector<Element>::size_type size_type;
|
||||
INLINE size_type size() const;
|
||||
INLINE const Element &get_element(size_type n) const;
|
||||
EXTENSION(const Element &__getitem__(size_type n) const);
|
||||
INLINE string get_data() const;
|
||||
INLINE string get_subdata(size_type n, size_type count) const;
|
||||
EXTENSION(PyObject *get_data() const);
|
||||
EXTENSION(PyObject *get_subdata(size_type n, size_type count) const);
|
||||
INLINE int get_ref_count() const;
|
||||
INLINE int get_node_ref_count() const;
|
||||
|
||||
|
@ -79,93 +79,26 @@ INLINE void Extension<PointerToArray<Element> >::
|
||||
__init__(PyObject *self, PyObject *source) {
|
||||
#if PY_VERSION_HEX >= 0x02060000
|
||||
if (PyObject_CheckBuffer(source)) {
|
||||
// User passed a buffer object.
|
||||
Py_buffer view;
|
||||
if (PyObject_GetBuffer(source, &view, PyBUF_CONTIG_RO) == -1) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"PointerToArray constructor requires a contiguous buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
if (view.itemsize != 1 && view.itemsize != sizeof(Element)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"buffer.itemsize does not match PointerToArray element size");
|
||||
return;
|
||||
}
|
||||
|
||||
if (view.len % sizeof(Element) != 0) {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"byte buffer is not a multiple of %zu bytes",
|
||||
sizeof(Element));
|
||||
return;
|
||||
}
|
||||
|
||||
if (view.len > 0) {
|
||||
this->_this->resize(view.len / sizeof(Element));
|
||||
memcpy(this->_this->p(), view.buf, view.len);
|
||||
}
|
||||
|
||||
PyBuffer_Release(&view);
|
||||
#else
|
||||
if (PyString_CheckExact(source)) {
|
||||
#endif
|
||||
// It's a byte sequence, or any object that exports the buffer protocol.
|
||||
this->set_data(source);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!PySequence_Check(source)) {
|
||||
// Don't allow a unicode object even though it's a sequence.
|
||||
if (!PySequence_Check(source) || PyUnicode_CheckExact(source)) {
|
||||
// If passed with a non-sequence, this isn't the right constructor.
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"PointerToArray constructor requires a sequence or buffer object");
|
||||
return;
|
||||
}
|
||||
|
||||
// If we were passed a Python string, then instead of storing it character-
|
||||
// at-a-time, just load the whole string as a data buffer. Not sure if this
|
||||
// case is still necessary - don't Python strbytes objects export the buffer
|
||||
// protocol, as above?
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
if (PyBytes_Check(source)) {
|
||||
int size = PyBytes_Size(source);
|
||||
if (size % sizeof(Element) != 0) {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"bytes object is not a multiple of %zu bytes",
|
||||
sizeof(Element));
|
||||
return;
|
||||
}
|
||||
|
||||
int num_elements = size / sizeof(Element);
|
||||
this->_this->insert(this->_this->begin(), num_elements, Element());
|
||||
|
||||
// Hope there aren't any constructors or destructors involved here.
|
||||
if (size != 0) {
|
||||
const char *data = PyBytes_AsString(source);
|
||||
memcpy(this->_this->p(), data, size);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (PyString_CheckExact(source)) {
|
||||
int size = PyString_Size(source);
|
||||
if (size % sizeof(Element) != 0) {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"str object is not a multiple of %zu bytes",
|
||||
sizeof(Element));
|
||||
return;
|
||||
}
|
||||
|
||||
int num_elements = size / sizeof(Element);
|
||||
this->_this->insert(this->_this->begin(), num_elements, Element());
|
||||
|
||||
// Hope there aren't any constructors or destructors involved here.
|
||||
if (size != 0) {
|
||||
const char *data = PyString_AsString(source);
|
||||
memcpy(this->_this->p(), data, size);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Now construct the internal list by copying the elements one-at-a-time
|
||||
// from Python.
|
||||
PyObject *push_back = PyObject_GetAttrString(self, "push_back");
|
||||
PyObject *dict = ((Dtool_PyInstDef *)self)->_My_Type->_PyType.tp_dict;
|
||||
PyObject *push_back = PyDict_GetItemString(dict, "push_back");
|
||||
if (push_back == NULL) {
|
||||
PyErr_BadArgument();
|
||||
return;
|
||||
@ -174,19 +107,20 @@ __init__(PyObject *self, PyObject *source) {
|
||||
// We need to initialize the this pointer before we can call push_back.
|
||||
((Dtool_PyInstDef *)self)->_ptr_to_object = (void *)this->_this;
|
||||
|
||||
int size = PySequence_Size(source);
|
||||
for (int i = 0; i < size; ++i) {
|
||||
Py_ssize_t size = PySequence_Size(source);
|
||||
this->_this->reserve(size);
|
||||
for (Py_ssize_t i = 0; i < size; ++i) {
|
||||
PyObject *item = PySequence_GetItem(source, i);
|
||||
if (item == NULL) {
|
||||
return;
|
||||
}
|
||||
PyObject *result = PyObject_CallFunctionObjArgs(push_back, item, NULL);
|
||||
PyObject *result = PyObject_CallFunctionObjArgs(push_back, self, item, NULL);
|
||||
Py_DECREF(item);
|
||||
if (result == NULL) {
|
||||
// Unable to add item--probably it wasn't of the appropriate type.
|
||||
PyErr_Print();
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"Element %d in sequence passed to PointerToArray "
|
||||
"Element %zd in sequence passed to PointerToArray "
|
||||
"constructor could not be added", i);
|
||||
return;
|
||||
}
|
||||
@ -213,15 +147,110 @@ __setitem__(size_t n, const Element &value) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This special constructor accepts a Python list of elements, or a Python
|
||||
* string (or a bytes object, in Python 3).
|
||||
* This returns the entire contents of the vector as a block of raw data in a
|
||||
* string (or bytes object, in Python 3).
|
||||
*
|
||||
* @deprecated use memoryview(pta) or bytearray(pta) instead.
|
||||
*/
|
||||
template<class Element>
|
||||
INLINE void Extension<ConstPointerToArray<Element> >::
|
||||
__init__(PyObject *self, PyObject *source) {
|
||||
PointerToArray<Element> array;
|
||||
invoke_extension(&array).__init__(self, source);
|
||||
*(this->_this) = MOVE(array);
|
||||
INLINE PyObject *Extension<PointerToArray<Element> >::
|
||||
get_data() const {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return PyBytes_FromStringAndSize((char *)this->_this->p(), sizeof(Element) * this->_this->size());
|
||||
#else
|
||||
return PyString_FromStringAndSize((char *)this->_this->p(), sizeof(Element) * this->_this->size());
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* This method exists mainly to access the data of the array easily from a
|
||||
* high-level language such as Python.
|
||||
*
|
||||
* This replaces the entire contents of the vector from a block of raw data
|
||||
* in a string (or bytes object, in Python 3).
|
||||
*/
|
||||
template<class Element>
|
||||
INLINE void Extension<PointerToArray<Element> >::
|
||||
set_data(PyObject *data) {
|
||||
#if PY_VERSION_HEX >= 0x02060000
|
||||
if (PyObject_CheckBuffer(data)) {
|
||||
// User passed a buffer object.
|
||||
Py_buffer view;
|
||||
if (PyObject_GetBuffer(data, &view, PyBUF_CONTIG_RO) == -1) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"PointerToArray.set_data() requires a contiguous buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
if (view.itemsize != 1 && view.itemsize != sizeof(Element)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"buffer.itemsize does not match PointerToArray element size");
|
||||
return;
|
||||
}
|
||||
|
||||
if (view.len % sizeof(Element) != 0) {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"byte buffer is not a multiple of %zu bytes",
|
||||
sizeof(Element));
|
||||
return;
|
||||
}
|
||||
|
||||
if (view.len > 0) {
|
||||
this->_this->resize(view.len / sizeof(Element));
|
||||
memcpy(this->_this->p(), view.buf, view.len);
|
||||
} else {
|
||||
this->_this->clear();
|
||||
}
|
||||
|
||||
PyBuffer_Release(&view);
|
||||
} else {
|
||||
Dtool_Raise_TypeError("PointerToArray.set_data() requires a buffer object");
|
||||
}
|
||||
#else
|
||||
// In Python 2.5 we didn't have the new buffer protocol, only str.
|
||||
if (PyString_CheckExact(data)) {
|
||||
int size = PyString_Size(data);
|
||||
if (size % sizeof(Element) != 0) {
|
||||
PyErr_Format(PyExc_ValueError,
|
||||
"str object is not a multiple of %zu bytes",
|
||||
sizeof(Element));
|
||||
return;
|
||||
}
|
||||
|
||||
int num_elements = size / sizeof(Element);
|
||||
this->_this->insert(this->_this->begin(), num_elements, Element());
|
||||
|
||||
// Hope there aren't any constructors or destructors involved here.
|
||||
if (size != 0) {
|
||||
const char *ptr = PyString_AsString(data);
|
||||
memcpy(this->_this->p(), ptr, size);
|
||||
} else {
|
||||
this->_this->clear();
|
||||
}
|
||||
} else {
|
||||
Dtool_Raise_TypeError("PointerToArray.set_data() requires a str");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns the contents of a portion of the vector--from element (n)
|
||||
* through element (n + count - 1)--as a block of raw data in a string (or
|
||||
* bytes object, in Python 3).
|
||||
*
|
||||
* @deprecated use memoryview(pta) or bytearray(pta) instead.
|
||||
*/
|
||||
template<class Element>
|
||||
INLINE PyObject *Extension<PointerToArray<Element> >::
|
||||
get_subdata(size_t n, size_t count) const {
|
||||
n = min(n, this->_this->size());
|
||||
count = max(count, n);
|
||||
count = min(count, this->_this->size() - n);
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return PyBytes_FromStringAndSize((char *)(this->_this->p() + n), sizeof(Element) * count);
|
||||
#else
|
||||
return PyString_FromStringAndSize((char *)(this->_this->p() + n), sizeof(Element) * count);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@ -233,6 +262,42 @@ __getitem__(size_t n) const {
|
||||
return (*this->_this)[n];
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns the entire contents of the vector as a block of raw data in a
|
||||
* string (or bytes object, in Python 3).
|
||||
*
|
||||
* @deprecated use memoryview(pta) or bytearray(pta) instead.
|
||||
*/
|
||||
template<class Element>
|
||||
INLINE PyObject *Extension<ConstPointerToArray<Element> >::
|
||||
get_data() const {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return PyBytes_FromStringAndSize((char *)this->_this->p(), sizeof(Element) * this->_this->size());
|
||||
#else
|
||||
return PyString_FromStringAndSize((char *)this->_this->p(), sizeof(Element) * this->_this->size());
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns the contents of a portion of the vector--from element (n)
|
||||
* through element (n + count - 1)--as a block of raw data in a string (or
|
||||
* bytes object, in Python 3).
|
||||
*
|
||||
* @deprecated use memoryview(pta) or bytearray(pta) instead.
|
||||
*/
|
||||
template<class Element>
|
||||
INLINE PyObject *Extension<ConstPointerToArray<Element> >::
|
||||
get_subdata(size_t n, size_t count) const {
|
||||
n = min(n, this->_this->size());
|
||||
count = max(count, n);
|
||||
count = min(count, this->_this->size() - n);
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return PyBytes_FromStringAndSize((char *)(this->_this->p() + n), sizeof(Element) * count);
|
||||
#else
|
||||
return PyString_FromStringAndSize((char *)(this->_this->p() + n), sizeof(Element) * count);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used to implement the buffer protocol, in order to allow efficient
|
||||
* access to the array data through a Python multiview object.
|
||||
@ -461,6 +526,9 @@ __getbuffer__(PyObject *self, Py_buffer *view, int flags) const {
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialization on __getbuffer__ for LMatrix3f.
|
||||
*/
|
||||
template<>
|
||||
INLINE int Extension<ConstPointerToArray<LMatrix3f> >::
|
||||
__getbuffer__(PyObject *self, Py_buffer *view, int flags) const {
|
||||
@ -488,6 +556,9 @@ __getbuffer__(PyObject *self, Py_buffer *view, int flags) const {
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialization on __getbuffer__ for LMatrix3d.
|
||||
*/
|
||||
template<>
|
||||
INLINE int Extension<ConstPointerToArray<LMatrix3d> >::
|
||||
__getbuffer__(PyObject *self, Py_buffer *view, int flags) const {
|
||||
@ -515,6 +586,9 @@ __getbuffer__(PyObject *self, Py_buffer *view, int flags) const {
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialization on __getbuffer__ for UnalignedLMatrix4f.
|
||||
*/
|
||||
template<>
|
||||
INLINE int Extension<ConstPointerToArray<UnalignedLMatrix4f> >::
|
||||
__getbuffer__(PyObject *self, Py_buffer *view, int flags) const {
|
||||
@ -542,6 +616,9 @@ __getbuffer__(PyObject *self, Py_buffer *view, int flags) const {
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialization on __getbuffer__ for UnalignedLMatrix4d.
|
||||
*/
|
||||
template<>
|
||||
INLINE int Extension<ConstPointerToArray<UnalignedLMatrix4d> >::
|
||||
__getbuffer__(PyObject *self, Py_buffer *view, int flags) const {
|
||||
|
@ -36,18 +36,29 @@ public:
|
||||
INLINE const Element &__getitem__(size_t n) const;
|
||||
INLINE void __setitem__(size_t n, const Element &value);
|
||||
|
||||
INLINE PyObject *get_data() const;
|
||||
INLINE void set_data(PyObject *data);
|
||||
INLINE PyObject *get_subdata(size_t n, size_t count) const;
|
||||
|
||||
INLINE int __getbuffer__(PyObject *self, Py_buffer *view, int flags);
|
||||
INLINE void __releasebuffer__(PyObject *self, Py_buffer *view) const;
|
||||
};
|
||||
|
||||
template<>
|
||||
INLINE int Extension<PointerToArray<LMatrix3f> >::__getbuffer__(PyObject *self, Py_buffer *view, int flags);
|
||||
INLINE int Extension<PointerToArray<LMatrix3f> >::
|
||||
__getbuffer__(PyObject *self, Py_buffer *view, int flags);
|
||||
|
||||
template<>
|
||||
INLINE int Extension<PointerToArray<LMatrix3d> >::__getbuffer__(PyObject *self, Py_buffer *view, int flags);
|
||||
INLINE int Extension<PointerToArray<LMatrix3d> >::
|
||||
__getbuffer__(PyObject *self, Py_buffer *view, int flags);
|
||||
|
||||
template<>
|
||||
INLINE int Extension<PointerToArray<UnalignedLMatrix4f> >::__getbuffer__(PyObject *self, Py_buffer *view, int flags);
|
||||
INLINE int Extension<PointerToArray<UnalignedLMatrix4f> >::
|
||||
__getbuffer__(PyObject *self, Py_buffer *view, int flags);
|
||||
|
||||
template<>
|
||||
INLINE int Extension<PointerToArray<UnalignedLMatrix4d> >::__getbuffer__(PyObject *self, Py_buffer *view, int flags);
|
||||
INLINE int Extension<PointerToArray<UnalignedLMatrix4d> >::
|
||||
__getbuffer__(PyObject *self, Py_buffer *view, int flags);
|
||||
|
||||
/**
|
||||
* This class defines the extension methods for ConstPointerToArray, which are
|
||||
@ -59,22 +70,30 @@ template<>
|
||||
template<class Element>
|
||||
class Extension<ConstPointerToArray<Element> > : public ExtensionBase<ConstPointerToArray<Element> > {
|
||||
public:
|
||||
INLINE void __init__(PyObject *self, PyObject *source);
|
||||
|
||||
INLINE const Element &__getitem__(size_t n) const;
|
||||
|
||||
INLINE PyObject *get_data() const;
|
||||
INLINE PyObject *get_subdata(size_t n, size_t count) const;
|
||||
|
||||
INLINE int __getbuffer__(PyObject *self, Py_buffer *view, int flags) const;
|
||||
INLINE void __releasebuffer__(PyObject *self, Py_buffer *view) const;
|
||||
};
|
||||
|
||||
template<>
|
||||
INLINE int Extension<ConstPointerToArray<LMatrix3f> >::__getbuffer__(PyObject *self, Py_buffer *view, int flags) const;
|
||||
INLINE int Extension<ConstPointerToArray<LMatrix3f> >::
|
||||
__getbuffer__(PyObject *self, Py_buffer *view, int flags) const;
|
||||
|
||||
template<>
|
||||
INLINE int Extension<ConstPointerToArray<LMatrix3d> >::__getbuffer__(PyObject *self, Py_buffer *view, int flags) const;
|
||||
INLINE int Extension<ConstPointerToArray<LMatrix3d> >::
|
||||
__getbuffer__(PyObject *self, Py_buffer *view, int flags) const;
|
||||
|
||||
template<>
|
||||
INLINE int Extension<ConstPointerToArray<UnalignedLMatrix4f> >::__getbuffer__(PyObject *self, Py_buffer *view, int flags) const;
|
||||
INLINE int Extension<ConstPointerToArray<UnalignedLMatrix4f> >::
|
||||
__getbuffer__(PyObject *self, Py_buffer *view, int flags) const;
|
||||
|
||||
template<>
|
||||
INLINE int Extension<ConstPointerToArray<UnalignedLMatrix4d> >::__getbuffer__(PyObject *self, Py_buffer *view, int flags) const;
|
||||
INLINE int Extension<ConstPointerToArray<UnalignedLMatrix4d> >::
|
||||
__getbuffer__(PyObject *self, Py_buffer *view, int flags) const;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Ugh... MSVC needs this because they still don't have a decent linker.
|
||||
|
Loading…
x
Reference in New Issue
Block a user