Gre*_*kel 5 c++ python callback cython stdvector
我试图通过Cython学习如何在C和Python之间使用回调,并一直在看这个演示.我想将一个Python函数应用于一个std :: vector/numpy.array并将结果存储在另一个中.我可以编译并运行没有错误,但最终矢量y没有被更改.
C++标题
// callback.hpp
#include<vector>
typedef double (*Callback)( void *apply, double &x );
void function( Callback callback, void *apply, vector<double> &x,
vector<double> &y );
Run Code Online (Sandbox Code Playgroud)
C++源码
// callback.cpp
#include "callback.hpp"
#include <iostream>
using namespace std;
void function( Callback callback, void* apply,
vector<double> &x, vector<double> &y ) {
int n = x.size();
for(int i=0;i<n;++i) {
y[i] = callback(apply,x[i]);
std::cout << y[i] << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
Cython标题
# cy_callback.pxd
import cython
from libcpp.vector cimport vector
cdef extern from "callback.hpp":
ctypedef double (*Callback)( void *apply, double &x )
void function( Callback callback, void* apply, vector[double] &x,
vector[double] &y )
Run Code Online (Sandbox Code Playgroud)
Cython源码
# cy_callback.pyx
from cy_callback cimport function
from libcpp.vector cimport vector
def pyfun(f,x,y):
function( cb, <void*> f, <vector[double]&> x, <vector[double]&> y )
cdef double cb(void* f, double &x):
return (<object>f)(x)
Run Code Online (Sandbox Code Playgroud)
我用相当的样板设置编译:python setup.py build_ext -i
# setup.py
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
import numpy
import os
os.environ["CC"] = "g++"
os.environ["CXX"] = "g++"
setup( name = 'callback',
ext_modules=[Extension("callback",
sources=["cy_callback.pyx","callback.cpp"],
language="c++",
include_dirs=[numpy.get_include()])],
cmdclass = {'build_ext': build_ext},
)
Run Code Online (Sandbox Code Playgroud)
最后使用Python脚本进行测试
# test.py
import numpy as np
from callback import pyfun
x = np.arange(11)
y = np.zeros(11)
pyfun(lambda x:x**2,x,y)
print(y)
Run Code Online (Sandbox Code Playgroud)
当y的元素在callback.cpp中设置时,正确的值将被打印到屏幕上,这意味着pyfun确实正在被正确评估,但是,在Python级别,y仍然全为零.
知道我做错了什么吗?
谢谢,伊恩。根据您的建议,我更改了代码以返回向量,而不是尝试就地修改它。这是有效的,虽然公认不是特别有效
回调.hpp
typedef double (*Callback)( void *apply, double x );
vector<double> function( Callback callback, void *apply,
const vector<double> &x );
Run Code Online (Sandbox Code Playgroud)
回调.cpp
vector<double> function( Callback callback, void* apply,
const vector<double> &x ) {
int n = x.size();
vector<double> y(n);
for(int i=0;i<n;++i) {
y[i] = callback(apply,x[i]);
}
return y;
}
Run Code Online (Sandbox Code Playgroud)
cy_callback.pxd
cdef extern from "callback.hpp":
ctypedef double (*Callback)( void *apply, const double &x )
vector[double] function( Callback callback, void* apply,
vector[double] &x )
Run Code Online (Sandbox Code Playgroud)
cy_callback.pyx
from cy_callback cimport function
from libcpp.vector cimport vector
def pyfun(f,x):
return function( cb, <void*> f, <const vector[double]&> x )
cdef double cb(void* f, double x ):
return (<object>f)(x)
Run Code Online (Sandbox Code Playgroud)
测试文件
import numpy as np
from callback import pyfun
x = np.arange(11)
y = np.zeros(11)
def f(x):
return x*x
y = pyfun(f,x)
print(y)
Run Code Online (Sandbox Code Playgroud)
当您将数组转换为向量时,会生成该数组的隐式副本。目前没有任何方法可以让向量获得已分配内存的所有权,因此唯一的解决方法是手动复制值或暴露std::copy给 cython。请参阅如何廉价地将 C 样式数组分配给 std::vector?。
| 归档时间: |
|
| 查看次数: |
3370 次 |
| 最近记录: |