簡體   English   中英

在Cython中使用move方法時出現編譯錯誤

[英]Compilation error when using the move method in Cython

我的問題類似於此處提出的問題-將C ++向量通過Cython傳遞給Numpy而不進行復制並自動進行內存管理,我也遇到了分段錯誤,但在解決此問題之前,我需要解決一些編譯錯誤Cython中的方法。

這是我擁有的最簡單的示例(只是網絡中提供的Rectangle示例的擴展

我想做什么我的C ++代碼返回點的雙端隊列。 它也可以返回點向量。 任何容器都可以

在cython代碼中,我想將返回的點的雙端隊列(for循環的每次迭代一個)存儲在一個集合中(例如vector或雙端隊列)。 該集合將是一個實例變量。

稍后,我想遍歷集合並將該雙端隊列的deque轉換為列表的python列表。 我認為這是我遇到細分錯誤的地方。

#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);
 };

矩形

   #include <deque>
   #include "Point.h"
   using std:deque;

   deque<Point> getAllPoints(Point query);

矩形文件

    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;

注意與鏈接的問題不同,我不是返回地址而是返回引用

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

最后

矩形

 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

我相信我在setup.pyx中設置了C ++ 17

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++',
                 )]

擴展名= 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 ++文件-我可以通過將其放在docstring中直接將代碼直接包含在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 ++推斷出模板類型。 由於某些原因,我無法完全理解,這似乎經常會產生錯誤的代碼。

我有兩個半解決方案:

  1. 不要告訴Cython move是模板功能。 而是告訴它您想要的重載:

     cdef extern from "<utility>" namespace "std" nogil: deque[Point] move(deque[Point]) 

    我認為這是最簡單的方法,可能也是我的方法。

  2. 如果您避免創建臨時area則C ++代碼可與模板一起使用:

     self.colOfPoints = move(self.getArea()) 

    我懷疑在這種情況下,您甚至可能不需要move -C ++可能會自動使用移動賦值運算符。

  3. 該答案聲稱提供了一個小的包裝,可幫助Cython調用正確的move (它也略微遺漏了它正在回答的問題上的實際問題...)。 我還沒有親自測試過,但是如果您想進行模板化移動,可能值得一試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM