我是Cython的新手,我想使用Cython来包装一个C/C++静态库.我做了一个简单的例子如下.
Test.h:
#ifndef TEST_H
#define TEST_H
int add(int a, int b);
int multipy(int a, int b);
#endif
Run Code Online (Sandbox Code Playgroud)
TEST.CPP
#include "test.h"
int add(int a, int b)
{
return a+b;
}
int multipy(int a, int b)
{
return a*b;
}
Run Code Online (Sandbox Code Playgroud)
然后我使用g ++来编译和构建它.
g++ -c test.cpp -o libtest.o
ar rcs libtest.a libtest.o
Run Code Online (Sandbox Code Playgroud)
所以现在我得到了一个名为libtest.a的静态库.
Test.pyx:
cdef extern from "test.h":
int add(int a,int b)
int multipy(int a,int b)
print add(2,3)
Run Code Online (Sandbox Code Playgroud)
Setup.py:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
ext_modules = …Run Code Online (Sandbox Code Playgroud) 我有一些简单的代码,可以执行以下操作.
它F使用+ -1条目迭代所有可能的长度n列表.对于每一个,它使用+ -1条目迭代所有可能的长度2n列表S,其中$ S $的前半部分只是下半部分的副本.代码计算F每个S长度子列表的内积n.对于每个F,S,它计算在第一个非零内积之前为零的内积.
这是代码.
#!/usr/bin/python
from __future__ import division
import itertools
import operator
import math
n=14
m=n+1
def innerproduct(A, B):
assert (len(A) == len(B))
s = 0
for k in xrange(0,n):
s+=A[k]*B[k]
return s
leadingzerocounts = [0]*m
for S in itertools.product([-1,1], repeat = n):
S1 = S + S
for F in itertools.product([-1,1], repeat = n):
i = 0
while (i<m):
ip = innerproduct(F, S1[i:i+n]) …Run Code Online (Sandbox Code Playgroud) 我有一个C++库,它有一个Python包装器(用SWIG编写).该库允许执行小的用户定义代码(回调),例如向量上的元素操作.即,而不只是一个+你可以做任意二进制函数.现在,这是通过接受二进制函数的可调用Python对象并调用它来实现的.它可以工作,但是比在每次迭代时都不需要在Python中反弹的代码慢大约80倍.
如何编写/构建/导入Cython函数可以传递到我的C++库中,以便它可以由C++库直接调用?
编辑: 如果我只是坚持C然后我会写类似的东西
EWise(double (*callback)(double, double))
Run Code Online (Sandbox Code Playgroud)
那么EWise就是callback(10, 20);这样的.我希望callback用Cython编写,使用用户想要的任何名称,并且必须通过Python以某种方式将指针传递给我的C++库.不知怎的,这是我不清楚的地方.
我正在尝试将cython模块data.pyx导入另一个cython模块user.pyx.一切都编译好,但是当我尝试在python模块中调用user.pyx时,我收到错误'ImportError:No module named data'.
一切都在同一个目录中.
package/
__init__.py #empty
setup.py
data.pxd
data.pyx
user.pyx
Run Code Online (Sandbox Code Playgroud)
我的setup.py
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
ext_modules = [
Extension("data", ["data.pyx"]),
Extension("user", ["user.pyx"],include_dirs = ['myPackageDir'])
]
setup(
name = 'app',
cmdclass = {'build_ext': build_ext},
ext_modules = ext_modules
)
Run Code Online (Sandbox Code Playgroud)
运行以下test.py将引发错误.
import user #this line raised the 'ImportError: No module named data' below
user.doSomething()
Run Code Online (Sandbox Code Playgroud)
我得到的例外是
Traceback:
File "test.py", line 1, in <module>
import package.user
File "user.pyx", line 1, in init user (user.c:3384)
ImportError: …Run Code Online (Sandbox Code Playgroud) 在编译一堆与Numpy接口的Cython生成的C文件时,我收到警告:
/usr/lib/pymodules/python2.7/numpy/core/include/numpy/__ufunc_api.h:226:1: warning: ‘_import_umath’ defined but not used [-Wunused-function]
Run Code Online (Sandbox Code Playgroud)
我似乎无法摆脱这一点.确定这可能类似于np.import_array(),它消除了相关的警告(并且实际上是使用Numpy C API所必需的),我尝试np.import_umath()了顶级,但警告仍然存在.我怎么摆脱它?
(Cython 0.17.4,Numpy 1.6.2.)
我有一个C函数声明如下:
void getIndexOfState(long *p, long C, long G, long B, long *state);
Run Code Online (Sandbox Code Playgroud)
现在我的cython包装器代码使用来自numpy数组的缓冲区语法:
cpdef int getIndexOfState(self, np.ndarray[np.int_t, ndim=1, mode="c"] s):
cdef long out
getIndexOfState(&out, self.C, self.G, self.B, <long*> s.data)
return out
Run Code Online (Sandbox Code Playgroud)
我想使用新的memoryview语法,我的问题是,在使用memoryview时如何将指针传递给数据?
我试过了:
cpdef int getIndexOfState(self, long[:] s):
cdef long out
getIndexOfState(&out, self.C, self.G, self.B, s)
return out
Run Code Online (Sandbox Code Playgroud)
当我试图编译模块时,它引发了"无法将类型'long [:]'分配给'long*'"错误.在调用C函数之前,有没有办法传递该指针而不将内存视图强制回到numpy数组?
我通过cython将我的python代码转换为c,然后编译.c文件并在我的项目中使用.so.我的问题:我__file__在我的python代码中使用,在使用gcc进行编译时,它不会出错.但是当我在其他python文件中运行程序并导入.so时,从__file__行显示错误.
怎么能解决这个问题?有什么方法可以替换__file__吗?
如何在cython中将类型化的内存视图转换为NumPy数组?文档有
cimport numpy as np
import numpy as np
numpy_array = np.asarray(<np.int32_t[:10, :10]> my_pointer)
Run Code Online (Sandbox Code Playgroud)
我把它当作我的情况
np.asarray(<np.float_t[:, :]> my_memview)
Run Code Online (Sandbox Code Playgroud)
使用这个编译器告诉我:
Can only create cython.array from pointer or array
Run Code Online (Sandbox Code Playgroud)
复制与否并非如此具有决定性.我找不到任何帮助.
我正在尝试构建一个Python多文件代码PyInstaller.为此,我编写了代码Cython,并使用.so生成的.py文件代替文件.
假设1号文件main.py和进口的有file_a.py和file_b.py,我得到file_a.so和file_b.so用Cython编译后.
当我放入main.py,file_a.so并file_b.so在一个文件夹中运行它"python main.py",它的工作原理.
但是当我构建它PyInstaller并尝试运行生成的可执行文件时,它会导致在file_a和中完成的导入错误file_b.
怎么解决这个问题?一种解决方案是导入所有标准模块main.py,这是有效的.但如果我不想改变我的代码,可以解决什么问题呢?
我已阅读在 Cython 中制作可执行文件和 BuvinJ 对如何有效地混淆 Python 代码的回答?并想测试编译后用 Cython 编译的源代码是否真的“不再存在”。确实流行使用 Cython 是一种保护 Python 源代码的方法,例如参见文章Protecting Python Sources With Cython。
让我们以这个简单的例子为例test.pyx:
import json, time # this will allow to see what happens when we import a library
print(json.dumps({'key': 'hello world'}))
time.sleep(3)
print(1/0) # division error!
Run Code Online (Sandbox Code Playgroud)
然后让我们使用 Cython:
cython test.pyx --embed
Run Code Online (Sandbox Code Playgroud)
这会产生一个test.c. 让我们编译它:
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64
cl test.c /I C:\Python37\include /link C:\Python37\libs\python37.lib
Run Code Online (Sandbox Code Playgroud)
有用!它生成了一个 140KB 的test.exe可执行文件,不错! …
cython ×10
python ×10
numpy ×3
algorithm ×1
arrays ×1
c++ ×1
callback ×1
memoryview ×1
numba ×1
performance ×1
pyinstaller ×1