Cython 在 `double (s.time_since_epoch().count())` 上返回 `Cython.Compiler.Errors.CompileError`

Posted

技术标签:

【中文标题】Cython 在 `double (s.time_since_epoch().count())` 上返回 `Cython.Compiler.Errors.CompileError`【英文标题】:Cython returns a `Cython.Compiler.Errors.CompileError` on `double (s.time_since_epoch().count())` 【发布时间】:2017-02-26 11:45:08 【问题描述】:

问题描述: 我想在 Python 中使用 Cython 访问 C++ 对象。 运行 python2 setup.py build_ext -i 时,我得到一个 Cython.Compiler.Errors.CompileError

你能看看下面,告诉我应该改变什么来让 Cython 编译我的代码吗?

当我尝试用 Cython 编译时,我得到:

$ python2 setup.py build_ext -i
Compiling ds5.pyx because it changed.
[1/1] Cythonizing ds5.pyx

Error compiling Cython file:
------------------------------------------------------------
...

    cdef cppclass os_time_service:
        #double get_time() const override
        double get_time()
        #static_cast<double>(ts.time_since_epoch().count())
        double (s.time_since_epoch().count())
                                    ^
------------------------------------------------------------

ds5.pyx:15:37: Expected '.', found 'count'
Traceback (most recent call last):
  File "setup.py", line 5, in <module>
    ext_modules = cythonize("ds5.pyx"))
  File "/usr/local/lib/python2.7/dist-packages/Cython/Build/Dependencies.py", line 934, in cythonize
    cythonize_one(*args)
  File "/usr/local/lib/python2.7/dist-packages/Cython/Build/Dependencies.py", line 1056, in cythonize_one
    raise CompileError(None, pyx_file)
Cython.Compiler.Errors.CompileError: ds5.pyx

h 文件中的相关行是:

$ view backend.h
#ifndef LIBREALSENSE_BACKEND_H
#define LIBREALSENSE_BACKEND_H

#include "../include/librealsense/rs.h"     // Inherit all type definitions in the public API

#include <memory>       // For shared_ptr
#include <functional>   // For function
#include <thread>       // For this_thread::sleep_for
#include <vector>
#include <algorithm>
#include <set>
#include <list>



const uint16_t VID_INTEL_CAMERA     = 0x8086;

namespace rsimpl

    namespace uvc
    
        class time_service
        
        public:
            virtual double get_time() const = 0;
            ~time_service() = default;
        ;

        class os_time_service: public time_service
        
        public:
            double get_time() const override
            
                auto ts = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
                return static_cast<double>(ts.time_since_epoch().count());
            
        ;
...

我的 pyx 文件是:

$ cat ds5.pyx
# distutils: language = c++
# distutils: sources = uvc-v4l2.cpp

cdef extern from "backend.h" namespace "rsimpl::uvc":
    #const uint16_t VID_INTEL_CAMERA     = 0x8086
    const unsigned short VID_INTEL_CAMERA     = 0x8086
    cdef cppclass time_service:
        #virtual double get_time() const = 0
        double get_time()

    cdef cppclass os_time_service:
        #double get_time() const override
        double get_time()
        #static_cast<double>(ts.time_since_epoch().count())
        double (s.time_since_epoch().count())

cdef class os_time_service_c:

    cdef os_time_service *_os_time_service_ptr

    def __cinit__(self):
        self._os_time_service_ptr = new os_time_service()
        if self._os_time_service_ptr == NULL:
            raise MemoryError()

    def __dealloc__(self):
        if self._os_time_service_ptr != NULL:
            del self._os_time_service_ptr

    cpdef double  get_time(self):
        return self._os_time_service_ptr.ts.time_since_epoch().count()

环境:

Ubuntu 16.04
Python 2.7.12
Cython 0.25.2

【问题讨论】:

【参考方案1】:

删除线

double (s.time_since_epoch().count())

解释: Cython 只需要知道函数 double get_time() 存在 - 它不需要知道实现(由您的 C++ 代码提供)。因此,无需尝试在 Cython 中重写实现。


我没有详细查看您的其余代码,因此那里也可能存在问题。不过有几个小cmets:

在构造函数中:

if self._os_time_service_ptr == NULL:
   raise MemoryError()

这是不必要的,因为如果分配失败,现代 C++ 会引发 std::bad_alloc,而不是返回 NULL(并且 Cython 会自动将其转换为 MemoryError)。

在析构函数中

if self._os_time_service_ptr != NULL:

是不必要的,因为删除NULL 是安全的。不过,这些都不会引起问题。

【讨论】:

以上是关于Cython 在 `double (s.time_since_epoch().count())` 上返回 `Cython.Compiler.Errors.CompileError`的主要内容,如果未能解决你的问题,请参考以下文章

在cython中并行化for循环:超越prange

Cython“模板参数中的未知类型”错误

Cython 创建 C 函数别名

在 Cython 的结构中使用指针数组

Cython 中动态大小的对象数组

内存泄漏(cython + numpy)