如何对数组使用 shared_ptr 和 make_shared?
How to use shared_ptr and make_shared with arrays?
我想使用 C++ shared_ptr 来替代原始 C 指针。作为一个简单的示例,以下代码似乎按预期工作:
from libcpp.memory cimport shared_ptr, allocator
cdef shared_ptr[double] spd
cdef allocator[double] allo
spd.reset(allo.allocate(13))
此处大小选择为13,但一般在编译时是不知道的。
我不确定这是否正确,但我没有遇到任何错误(还没有内存泄漏和段错误)。我很好奇 make_shared.
是否有更优的解决方案
但我不能使用 C++11 数组,因为 Cython 不允许文字作为模板,例如像
cdef shared_ptr[array[double]] spd = make_shared[array[double,13]]()
和应该与 C++20 编译器(例如 gcc 10)一起工作的“普通”数组以某种方式引起问题:
# Cython error "Expected an identifier or literal"
cdef shared_ptr[double[]] spd = make_shared[double[]](3)
# Can't get ptr to work
ctypedef double[] darr
cdef shared_ptr[darr] spd = make_shared[darr](13)
cdef double* ptr = spd.get() # or spd.get()[0] or <double*> spd.get()[0] or ...
分配器解决方案是正确且最好的解决方案还是有其他方法?
这是我要处理的
cdef extern from *:
"""
template <typename T>
struct Ptr_deleter{
size_t nn;
void (*free_ptr)(T*, size_t);
Ptr_deleter(size_t nIn, void (*free_ptrIn)(T*, size_t)){
this->nn = nIn;
this->free_ptr = free_ptrIn;
};
void operator()(T* ptr){
free_ptr(ptr, nn);
};
};
template <typename T>
std::shared_ptr<T> ptr_to_sptr (T* ptr, size_t nn, void (*free_ptr)(T*, size_t)) {
Ptr_deleter dltr(nn, free_ptr);
std::shared_ptr<T> sp (ptr, dltr);
return sp;
};
"""
shared_ptr[double] d_ptr_to_sptr "ptr_to_sptr"(double* ptr, size_t nn, void (*free_ptr)(double*, size_t) nogil) nogil
cdef void free_d_ptr(double* ptr, size_t nn) nogil:
free(ptr)
cdef shared_ptr[double] sp_d_empty(size_t nn) nogil:
return d_ptr_to_sptr(<double*> nullCheckMalloc(nn*sizeof(double)), nn, &free_d_ptr)
我的理解是,处理 malloc
ed 数组的“正确”方法是像我一样使用自定义删除器。我个人更喜欢坚持使用 somewhat-raw C 指针(double*
而不是 double[]
或其他东西),因为它在 Cython 和我的项目中更自然。
我认为了解如何针对更复杂的数据类型更改 free_ptr
相当容易。对于简单的数据类型,它可以用更少的行和更少的复杂性来完成,但我希望有相同的基础。
我喜欢我的解决方案,因为我可以将现有的 Cython/C 代码原始指针“包装”在 shared_ptr
.
中
在使用 C++(尤其是 C++20 等较新的标准)时,我认为逐字代码通常是必需的。但是我有意在 Cython 中定义了 free_d_ptr
,因此可以很容易地使用现有的 Cython 代码来处理对 free/clear/whatever 数组所做的实际工作。
我没有让 C++11 std::arrays
工作,而且它在 Cython 中显然不是一般的“正确”可能(参见 )。
我也没有得到 double[]
或类似的工作(在 C++20 中是可能的),但是对于逐字的 C++ 代码,我认为这在 Cython 中应该是可行的。无论如何,我更喜欢 C-like pointers/arrays
我想使用 C++ shared_ptr 来替代原始 C 指针。作为一个简单的示例,以下代码似乎按预期工作:
from libcpp.memory cimport shared_ptr, allocator
cdef shared_ptr[double] spd
cdef allocator[double] allo
spd.reset(allo.allocate(13))
此处大小选择为13,但一般在编译时是不知道的。 我不确定这是否正确,但我没有遇到任何错误(还没有内存泄漏和段错误)。我很好奇 make_shared.
是否有更优的解决方案但我不能使用 C++11 数组,因为 Cython 不允许文字作为模板,例如像
cdef shared_ptr[array[double]] spd = make_shared[array[double,13]]()
和应该与 C++20 编译器(例如 gcc 10)一起工作的“普通”数组以某种方式引起问题:
# Cython error "Expected an identifier or literal"
cdef shared_ptr[double[]] spd = make_shared[double[]](3)
# Can't get ptr to work
ctypedef double[] darr
cdef shared_ptr[darr] spd = make_shared[darr](13)
cdef double* ptr = spd.get() # or spd.get()[0] or <double*> spd.get()[0] or ...
分配器解决方案是正确且最好的解决方案还是有其他方法?
这是我要处理的
cdef extern from *:
"""
template <typename T>
struct Ptr_deleter{
size_t nn;
void (*free_ptr)(T*, size_t);
Ptr_deleter(size_t nIn, void (*free_ptrIn)(T*, size_t)){
this->nn = nIn;
this->free_ptr = free_ptrIn;
};
void operator()(T* ptr){
free_ptr(ptr, nn);
};
};
template <typename T>
std::shared_ptr<T> ptr_to_sptr (T* ptr, size_t nn, void (*free_ptr)(T*, size_t)) {
Ptr_deleter dltr(nn, free_ptr);
std::shared_ptr<T> sp (ptr, dltr);
return sp;
};
"""
shared_ptr[double] d_ptr_to_sptr "ptr_to_sptr"(double* ptr, size_t nn, void (*free_ptr)(double*, size_t) nogil) nogil
cdef void free_d_ptr(double* ptr, size_t nn) nogil:
free(ptr)
cdef shared_ptr[double] sp_d_empty(size_t nn) nogil:
return d_ptr_to_sptr(<double*> nullCheckMalloc(nn*sizeof(double)), nn, &free_d_ptr)
我的理解是,处理 malloc
ed 数组的“正确”方法是像我一样使用自定义删除器。我个人更喜欢坚持使用 somewhat-raw C 指针(double*
而不是 double[]
或其他东西),因为它在 Cython 和我的项目中更自然。
我认为了解如何针对更复杂的数据类型更改 free_ptr
相当容易。对于简单的数据类型,它可以用更少的行和更少的复杂性来完成,但我希望有相同的基础。
我喜欢我的解决方案,因为我可以将现有的 Cython/C 代码原始指针“包装”在 shared_ptr
.
在使用 C++(尤其是 C++20 等较新的标准)时,我认为逐字代码通常是必需的。但是我有意在 Cython 中定义了 free_d_ptr
,因此可以很容易地使用现有的 Cython 代码来处理对 free/clear/whatever 数组所做的实际工作。
我没有让 C++11 std::arrays
工作,而且它在 Cython 中显然不是一般的“正确”可能(参见
我也没有得到 double[]
或类似的工作(在 C++20 中是可能的),但是对于逐字的 C++ 代码,我认为这在 Cython 中应该是可行的。无论如何,我更喜欢 C-like pointers/arrays