所以它看起來像唯一真正的解決方案是基於pybuffer.i
可以從C++複製到現有緩衝區的東西。如果您添加到痛飲包括文件:
%insert("python") %{
import numpy as np
%}
/*! Templated function to copy contents of a container to an allocated memory
* buffer
*/
%inline %{
//==== ADDED BY numpy.i
#include <algorithm>
template < typename Container_T >
void copy_to_buffer(
const Container_T& field,
typename Container_T::value_type* buffer,
typename Container_T::size_type length
)
{
// ValidateUserInput(length == field.size(),
// "Destination buffer is the wrong size");
// put your own assertion here or BAD THINGS CAN HAPPEN
if (length == field.size()) {
std::copy(field.begin(), field.end(), buffer);
}
}
//====
%}
%define TYPEMAP_COPY_TO_BUFFER(CLASS...)
%typemap(in) (CLASS::value_type* buffer, CLASS::size_type length)
(int res = 0, Py_ssize_t size_ = 0, void *buffer_ = 0) {
res = PyObject_AsWriteBuffer($input, &buffer_, &size_);
if (res < 0) {
PyErr_Clear();
%argument_fail(res, "(CLASS::value_type*, CLASS::size_type length)",
$symname, $argnum);
}
$1 = ($1_ltype) buffer_;
$2 = ($2_ltype) (size_/sizeof($*1_type));
}
%enddef
%define ADD_NUMPY_ARRAY_INTERFACE(PYVALUE, PYCLASS, CLASS...)
TYPEMAP_COPY_TO_BUFFER(CLASS)
%template(_copy_to_buffer_ ## PYCLASS) copy_to_buffer<CLASS>;
%extend CLASS {
%insert("python") %{
def __array__(self):
"""Enable access to this data as a numpy array"""
a = np.ndarray(shape=(len(self),), dtype=PYVALUE)
_copy_to_buffer_ ## PYCLASS(self, a)
return a
%}
}
%enddef
那麼你可以做一個容器 「numpy的」 -able與
%template(DumbVectorFloat) DumbVector<double>;
ADD_NUMPY_ARRAY_INTERFACE(float, DumbVectorFloat, DumbVector<double>);
然後在Python,只是做:
# dvf is an instance of DumbVectorFloat
import numpy as np
my_numpy_array = np.asarray(dvf)
這隻有一個Python < - > C++翻譯調用的開銷,而不是由典型長度爲N的數組產生的N.
此代碼的稍微更加完整的版本是我的PyTRT project at github的一部分。
你能否提供一些實際實施的更多細節?有沒有辦法做到這一點,而不必根據Numpy頭文件編譯我的項目?謝謝。 – 2011-03-24 19:21:25
它也說這是一個傳統的界面。 – 2011-03-24 19:48:16
'__array_interface__'只是一個普通的字典,裏面有簡單的類型。無需使用任何Numpy頭文件進行編譯。忽略將其稱爲「傳統」的註釋。我以爲我已經刪除了。如果你喜歡,你可以實現PEP 3118緩衝接口,但這很容易。 – 2011-05-20 23:39:57