我有以下 C++ 类:
。H
class ALabSet: public LabSet {
public:
PyObject *m_obj;
ALabSet(PyObject *obj);
virtual ~ALabSet();
PyObject *GetPyObj();
};
Run Code Online (Sandbox Code Playgroud)
.CPP
ALabSet::ALabSet(PyObject *obj): LabSet() {
this->m_obj = obj;
// Provided by "cyelp_api.h"
if (import_cyelp()) {
} else {
Py_XINCREF(this->m_obj);
}
}
ALabSet::~ALabSet() {
Py_XDECREF(this->m_obj);
}
PyObject *ALabSet::GetPyObj() {
return this->m_obj;
}
Run Code Online (Sandbox Code Playgroud)
我用 Cython 将其暴露如下:
cdef extern from "adapter/ALabSiteSetsManager.h" namespace "elps" :
cdef cppclass ALabSet:
ALabSet(PyObject *)
PyObject *GetPyObj()
cdef class PyLabSet:
cdef ALabSet *thisptr
def __cinit__(self):
self.thisptr = new ALabSet(<PyObject *>self) …Run Code Online (Sandbox Code Playgroud) 我在 Mac OS X 下编译了一个module.pyx文件module.so,现在我可以将它用于:
from module import method1
然而,同样的.so文件在Linux上不起作用,我必须module.so在Linux下编译一个新的。
所以问题是,如何使用 Cython 编写跨平台(Mac 和 Linux)模块?
我是 Cython 的新手,正在尝试学习如何将其与 numpy 一起使用来加速代码。我一直在关注此链接中的教程。
我在这里复制了他们的代码:
from __future__ import division
import numpy as np
# "cimport" is used to import special compile-time information
# about the numpy module (this is stored in a file numpy.pxd which is
# currently part of the Cython distribution).
cimport numpy as np
# We now need to fix a datatype for our arrays. I've used the variable
# DTYPE for this, which is assigned to the usual NumPy runtime
# type info …Run Code Online (Sandbox Code Playgroud) 我尝试直接使用 Cython 而不是 Python 加载 time.himport time但它不起作用。
我得到的只是一个错误
Call with wrong number of arguments (expected 1, got 0)
Run Code Online (Sandbox Code Playgroud)
用下面的代码
cdef extern from "time.h" nogil:
ctypedef int time_t
time_t time(time_t*)
def test():
cdef int ts
ts = time()
return ts
Run Code Online (Sandbox Code Playgroud)
和
Cannot assign type 'long' to 'time_t *'
Run Code Online (Sandbox Code Playgroud)
用下面的代码
cdef extern from "time.h" nogil:
ctypedef int time_t
time_t time(time_t*)
def test():
cdef int ts
ts = time(1)
return ts
Run Code Online (Sandbox Code Playgroud)
有了数学日志我可以简单地做
cdef extern from "math.h":
double log10(double x)
Run Code Online (Sandbox Code Playgroud)
怎么随着时间的推移就不可能了呢?
假设我有一个如下结构的 python 包:
foo/
__init__.py
setup.py
bar/
__init__.py
bar.pyx
Run Code Online (Sandbox Code Playgroud)
的内容setup.py是
from distutils.core import setup
from Cython.Build import cythonize
import numpy as np
setup(
ext_modules=cythonize("bar/bar.pyx"),
include_dirs=[np.get_include()]
)
Run Code Online (Sandbox Code Playgroud)
然后我就跑
python setup.py build_ext --inplace
Run Code Online (Sandbox Code Playgroud)
因为我需要将编译后的文件bar.so准确放置在bar/. 但是前面的命令foo/bar/在 下创建了一个新目录bar,并放在bar.so那里,比如说,
foo/
__init__.py
setup.py
bar/
__init__.py
bar.pyx
foo/
bar/
bar.so
Run Code Online (Sandbox Code Playgroud)
而我需要的是
foo/
__init__.py
setup.py
bar/
__init__.py
bar.pyx
bar.so
Run Code Online (Sandbox Code Playgroud)
这些烦人的事情发生在我转身foo成为bar一个包裹之后。如果我删除foo/__init__.py然后会出现在,仍然不会bar/__init__.py。我已阅读手册,但没有找到解决此问题的选项。bar.sofoo/foo/bar/
那么如果我要求bar.so出现在正确的位置,同时保留这两个__init__.py文件该怎么办呢?
我的部分工作需要大量计算,但它们通常相当简单,原则上可以很容易地与 Cython 的 prange 并行完成,需要 nogil。然而,鉴于我尝试编写 Cython 代码,重点是将 cdef 类作为构建块,我遇到了问题。
假设我有一个数值积分例程或类似的例程,它将函数指针作为输入
ctypedef double (* someFunctionPointer) (double tt) nogil
cdef double integrationRoutine(someFunctionfointer ff) nogil:
# Doing something
# ...
return result
Run Code Online (Sandbox Code Playgroud)
现在我的每个集成点实际上是一个“更大的”模拟(很多参数等等我加载/设置/输入或其他),它是在一个类中实现的。所以我最初的方法是做类似的事情
cdef class SimulationClass:
cdef double simulationFunctionPointer(SimulationClass self, double tt) nogil:
# ...
Run Code Online (Sandbox Code Playgroud)
我认为我可以将“simulationFunctionPointer”交给“integrationRoutine”,这样就可以了。由于 self 论证,这当然行不通。
我所有的解决方法要么需要
对于如何解决这个问题有什么建议或想法吗?我的第一种方法可以用其他语言(例如 C++)吗?
干杯
我正在寻找一种在 cython 文件中添加预编译器逻辑的解决方案。
我已经为 C++ 中的硬件设备 API 编写了一个 cython 包装器。这是一个 cython 项目,通常使用 MSVC for python 2.7 和 3.6 进行编译。整个包是用 cython 编写的,不需要外部 C++ 或头文件。
最初,我编写这个软件是为了在 Windows 计算机上使用,因此我使用了许多基本 winapi 函数来帮助访问内核事件循环和 winapi 错误消息。它工作得很好,但我还想添加跨平台编译的功能。这需要我完全替换几个关键功能才能使其在linux机器上运行。例如,硬件 API 甚至根据操作系统的不同而具有不同的事件处理函数。此外,winapi 事件处理也需要更换。
现在,我将整个项目编译成一个模块以简化导入。所有代码都驻留在编译成hwmodule.pyd文件的同一个 pyx 文件中。但是,为了实现跨平台编译的目标,我需要在安装时将几个小 pyx 文件修补到一起。这种解决方案并不优雅并且难以维护。更不用说,培训其他可能想要添加到项目中的人会更加困难。
理想情况下,我能够将 cython 写入 c 编译时标志,这些标志根据标志或变量进行解释和编译。cython 有什么解决方案可以实现我的目标吗?或者,是否有一个不同的组织可以优雅且易于维护?
一些看似合理的语法示例(可能存在也可能不存在)类似于 c 或 python 中的语法:
使用#ifdef或类似的声明
#ifdef __WINAPI
def foo():
print('bar win')
#else
def foo():
print('bar linux')
#endif
Run Code Online (Sandbox Code Playgroud)使用类似 python 的with块
with ifdef('__WINAPI'):
def foo():
print('bar win')
Run Code Online (Sandbox Code Playgroud)用类似 cython 的行结束符结束函数 …
在 Ubuntu 14.04 上,我使用 Pycharm 专业版。当我启动调试会话时,我在 Pycharm 的事件日志中看到以下消息:
Python 调试器扩展可用
Cython 扩展加速 Python 调试
单击将Install出现一个弹出窗口,其中包含错误消息:
我也在这里描绘了文本,以便其他人更容易找到:
编译 Cython 扩展错误
非零退出代码 (1):
无法执行“gcc”:没有这样的文件或目录
错误:命令“gcc”失败,退出状态为 1
寻找解决方案:
我根据上面提到的链接手动编译了Cython speedups /usr/bin/python3 /<PYCHARM_INSTALLATION_PATH>/helpers/pydev/setup_cython.py build_ext --inplace:。这成功完成,但对错误消息没有帮助。
我添加了 python-3.6-dev 存储库:
sudo add-apt-repository ppa:deadsnakes/ppa,执行:sudo apt-get update && sudo apt-get dist-upgrade
并安装了 python-3.6-dev:sudo apt-get install python3.6-dev
它成功完成,但不会更改上面弹出的错误消息。
我还可以检查或执行什么?
编辑 有关 gcc 的安装,如下所示:
user@user-computer:~$ gcc
The program 'gcc' is currently not installed. You can install it by typing:
sudo apt-get install …Run Code Online (Sandbox Code Playgroud) 对于我当前的项目,我需要能够计算具有 GF(2) 条目的 64*64 矩阵的排名。我想知道是否有人有好的解决方案。
我一直在使用pyfinite来实现这一点,但它相当慢,因为它是一个纯 python 实现。我还尝试对我一直在使用的代码进行 cythonise,但由于依赖 pyfinite 而遇到了问题。
我的下一个想法是用 cython 编写我自己的类,但这对于我的需要来说似乎有点矫枉过正。
我需要以下功能
matrix = GF2Matrix(size=64) # creating a 64*64 matrix
matrix.setRow(i, [1,0,1....,1]) # set row using list
matrix += matrix2 # addition of matrices
rank(matrix) # then computing the rank
Run Code Online (Sandbox Code Playgroud)
感谢您的任何想法。
我设法让 Cython 处理一个简单的 C++ 文件。但是当我尝试让它为我们的项目工作时,我遇到了路径问题。
当我运行“python3.6 setup.py build_ext --inplace”时,出现以下错误:
myapp.h:12:10: fatal error: base/file1.h: No such file or directory
#include <base/file1.h>
^~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
这是我的文件夹结构:
.
|-- base
| |-- file1.h
| \-- file1.cpp
|
|-- app
| |-- app.pyx
| \-- setup.py
|
|-- myapp.cpp
\-- myapp.h
Run Code Online (Sandbox Code Playgroud)
这是setup.py:
from distutils.core import setup, Extension
from Cython.Build import cythonize
setup(ext_modules = cythonize(Extension(
"app",
sources=["app.pyx", "myapp.cpp"],
language="c++",
)))
Run Code Online (Sandbox Code Playgroud)
在 myapp.h 中,有这一行:
#include <base/file1.h>
Run Code Online (Sandbox Code Playgroud) cython ×10
python ×8
c++ ×2
destructor ×1
finite-field ×1
linux ×1
macos ×1
matrix ×1
numpy ×1
pycharm ×1
python-2.7 ×1
setup.py ×1
time ×1