在Cython中使用移动方法时的汇编误差
Compilation error when using the move method in Cython
我的问题类似于这里问的问题 - 将C 向量通过Cython传递给Numpy而无需自动复制和照顾内存管理,我也会得到分段错误,但在我可以解决它之前我在Cython中的移动方法有一些汇编错误。
这是我拥有的最简单的示例(只是Net提供的矩形示例的扩展
我想做什么我的C 代码返回点数。它也可以返回积分的向量。任何容器都会做
在Cython代码中,我想将返回的点(每次迭代循环的迭代(存储在集合中(例如向量或Deque(中。该集合将是实例变量。
稍后,我想通过集合进行迭代,然后将点的Deque转换为列表列表。我相信我相信我会遇到细分错误。
point.h
#ifndef POINT_H
#define POINT_H
class Point
{
private:
double coordinate1,coordinate2;
public:
virtual double getCoordinate1() const;
virtual double getCoordinate2() const ;
virtual void setCoordinate1(double coordinate1);
virtual void setCoordinate2(double coordinate2);
};
Rectangle.h
#include <deque>
#include "Point.h"
using std:deque;
deque<Point> getAllPoints(Point query);
Rectangle.cpp
include "Rectangle.h"
deque<Point> Rectangle::getAllPoints(Point query)
{
deque<Point> deq;
for (int i = 0;i < 10000; ++i)
{
deq.push_back(query);
}
return deq;
NOTE 与链接的问题不同,我没有返回地址,而是返回参考
rect.pxd
cdef extern from "<utility>" namespace "std" nogil:
T move[T](T) #
cdef extern from "Point.h":
cdef cppclass Point:
Point() nogil except +
double getCoordinate1()
double getCoordinate2()
void setCoordinate1(double coordinate1) nogil
void setCoordinate2(double coordinate2) nogil
cdef cppclass SphericalPoint(Point):
SphericalPoint() nogil except +
double getCoordinate1()
double getCoordinate2()
void setCoordinate1(double lat) nogil
void setCoordinate2(double lon) nogil
cdef extern from "Rectangle.h" namespace "shapes":
cdef cppclass Rectangle:
Rectangle(int, int, int, int) except + nogil
deque[Point] getArea(Point p) nogil
最后
rect.pyx
cdef class PyRectangle:
cdef Rectangle *rect
cdef deque[Point] colOfPoints
def __cinit__(self, int x0, int y0, int x1, int y1):
self.rect = new Rectangle(x0, y0, x1, y1)
self.colOfPoints = deque[Point]()
def performCalc(self,maxDistance,chunk):
cdef deque[Point] area
cdef double[:,:] gPoints
gPoints = memoryview(chunk)
for i in range(0,len(gPoints)):
with nogil:
area = self.getArea(gPoints[i])
self.colOfPoints = move(area)
cdef deque[Point] getArea(self,double[:] p) nogil:
cdef deque[Point] area
area = self.rect.getArea(point)
return area
我相信我正在设置c 17在setup.pyx
setup.py
os.environ['CFLAGS'] = '-O3 -Wall -std=c++17'
ext_modules = [Extension("rect",
["rect.pyx","Rectangle.cpp"],
include_dirs=['/usr/local/include'],
extra_link_args=["-std=c++17"],
language='c++',
)]
extensions = cythonize(ext_modules,language_level =" 3"(
我得到这些汇编错误
rect.cpp: In function ‘PyObject* __pyx_pf_4rect_11PyRectangle_6performCalc(__pyx_obj_4rect_PyRectangle*, PyObject*, PyObject*)’:
rect.cpp:3781:81: error: no matching function for call to ‘move<std::deque<Point, std::allocator<Point> > >(std::deque<Point>&)’
__pyx_v_self->colOfPoints = std::move<std::deque<Point> >(__pyx_v_area);
^
In file included from /usr/include/c++/7 /bits/nested_exception.h:40:0,
from /usr/include/c++/7/exception:143,
from /usr/include/c++/7/ios:39,
from rect.cpp:632:
/usr/include/c++/7/bits/move.h:98:5: note: candidate: template<class _Tp> constexpr typename std::remove_reference< <template-parameter-1-1> >::type&& std::move(_Tp&&)
move(_Tp&& __t) noexcept
^~~~
/usr/include/c++/7/bits/move.h:98:5: note: template argument deduction/substitution failed:
rect.cpp:3781:81: note: cannot convert ‘__pyx_v_area’ (type ‘std::deque<Point>’) to type ‘std::deque<Point>&&’
__pyx_v_self->colOfPoints = std::move<std::deque<Point> >(__pyx_v_area);
^
In file included from /usr/include/c++/7/bits/char_traits.h:39:0,
from /usr/include/c++/7/ios:40,
from rect.cpp:632:
/usr/include/c++/7/bits/stl_algobase.h:479:5: note: candidate: template<class _II, class _OI> _OI std::move(_II, _II, _OI)
move(_II __first, _II __last, _OI __result)
^~~~
/usr/include/c++/7/bits/stl_algobase.h:479:5: note: template argument deduction/substitution failed:
rect.cpp:3781:81: note: candidate expects 3 arguments, 1 provided
__pyx_v_self->colOfPoints = std::move<std::deque<Point> >(__pyx_v_area);
^
In file included from /usr/include/c++/7/deque:66:0,
from rect.cpp:636:
/usr/include/c++/7/bits/deque.tcc:1048:5: note: candidate: template<class _Tp> std::_Deque_iterator<_Tp, _Tp&, _Tp*> std::move(std::_Deque_iterator<_Tp, const _Tp&, const _Tp*>, std::_Deque_iterator<_Tp, const _Tp&, const _Tp*>, std::_Deque_iterator<_Tp, _Tp&, _Tp*>)
move(_Deque_iterator<_Tp, const _Tp&, const _Tp*> __first,
^~~~
/usr/include/c++/7/bits/deque.tcc:1048:5: note: template argument deduction/substitution failed:
rect.cpp:3781:81: note: candidate expects 3 arguments, 1 provided
__pyx_v_self->colOfPoints = std::move<std::deque<Point> >(__pyx_v_area);
^
In file included from /usr/include/c++/7/deque:64:0,
from rect.cpp:636:
/usr/include/c++/7/bits/stl_deque.h:424:5: note: candidate: template<class _Tp> std::_Deque_iterator<_Tp, _Tp&, _Tp*> std::move(std::_Deque_iterator<_Tp, _Tp&, _Tp*>, std::_Deque_iterator<_Tp, _Tp&, _Tp*>, std::_Deque_iterator<_Tp, _Tp&, _Tp*>)
move(_Deque_iterator<_Tp, _Tp&, _Tp*> __first,
^~~~
/usr/include/c++/7/bits/stl_deque.h:424:5: note: template argument deduction/substitution failed:
rect.cpp:3781:81: note: candidate expects 3 arguments, 1 provided
__pyx_v_self->colOfPoints = std::move<std::deque<Point> >(__pyx_v_area);
以下是我用来重现您的问题的稍微简化版本。我只是将其包括在内,以说明如何进一步剪切您的示例 - 请注意,我不需要使用C 文件 - 我可以通过将代码直接包含在PYX文件中。
#distutils: language = c++
from libcpp.deque cimport deque
cdef extern from *:
"""
#include <deque>
using std::deque;
class Point{};
deque<Point> getAllPoints() {
deque<Point> deq;
for (int i=0; i<10000; ++i) {
deq.push_back(Point{});
}
return deq;
}
"""
cdef cppclass Point:
pass
deque[Point] getAllPoints()
cdef extern from "<utility>" namespace "std" nogil:
T move[T](T)
cdef class PyRectange:
cdef deque[Point] colOfPoints
def something(self):
cdef deque[Point] area = self.getArea()
self.colOfPoints = move(area)
cdef deque[Point] getArea(self):
return getAllPoints()
基本问题是,当Cython生成模板的C 代码时,它会写入std::move<deque<Point>>(area)
而不是std::move(area)
并让C 推断模板类型。由于原因,我不完全理解这似乎在很多时候都会生成错误的代码。
我有两个半解决方案:
不要告诉Cython
move
是模板功能。相反,只需告诉它您想要的过载:cdef extern from "<utility>" namespace "std" nogil: deque[Point] move(deque[Point])
我认为这是最简单的,也许是我的方法。
如果避免创建临时
area
,则C 代码确实可以与模板一起使用:self.colOfPoints = move(self.getArea())
我怀疑在这种情况下,您甚至不需要
move
-C 可能会自动使用移动分配操作员。这个答案声称提出了一个小包装器,可以帮助Cython致电正确的
move
(在回答的问题上,它也有些错过了实际问题...(。我没有自己测试过,但是如果您想要模板的举动,那可能值得一试。
- 为什么在浮点中从大到小会引入更多的误差
- 为什么我的C++程序的程序集输出充满了 .ascii,没有汇编代码?
- 在 emscripten 网页汇编正在运行期间更新进度条?
- 为什么我们不编写可以处理C++标识符的汇编器和链接器?
- 在什么情况下,我想在 C/C++ 代码中使用内联汇编代码
- 为什么 memcpy() 和其他类似的函数使用汇编?
- [[可能]]和[[不太可能]]影响程序汇编的简单示例?
- 基于相邻元素 c++ 的分段误差范围的循环
- 在Cython中使用移动方法时的汇编误差
- typedef void汇编误差(是初始化的(使用dectType))
- C (MACOS)的汇编误差
- 使用C 中的constexpr汇编误差
- MSYS2上使用GCC 8.2.1的本本汇编误差
- 使用MPIC 误差进行C 汇编
- 传递variadic arg to模板函数时的汇编误差
- 汇编误差:从CSV转换为LIBSVM格式
- variadic模板递归返回类型扣除汇编误差
- 使用模板和lambda的汇编误差与clang
- Boost ::几何3D多边形交叉汇编误差
- 无序的一组对,汇编误差