gpt4 book ai didi

python - 如何使用 Cython 公开将 C++ 对象返回给 Python 的函数?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:33:47 25 4
gpt4 key购买 nike

我正在使用 Cython 构建 C++<->Python 绑定(bind),但我找不到如何从 Python 方法返回 C++ 对象。

更具体地说,在编译 peak_detection_.pyx 时,如下所示,我得到

peak_detection_.pyx:35:36: Cannot convert 'vector[Peak]' to Python object

最后几行

def getPeaks(self,data):
return self.thisptr.getPeaks(data)

我理解这个错误,但我不介意一些关于如何修复它的帮助/指示。

peak_detection.hpp

#ifndef PEAKDETECTION_H
#define PEAKDETECTION_H

#include <string>
#include <map>
#include <vector>

#include "peak.hpp"


class PeakDetection
{
public:
PeakDetection(std::map<std::string, std::string> config);
std::vector<Peak> getPeaks(std::vector<float> &data);

private:
float _threshold;
};

#endif

peak_detection.cpp

#include <iostream>
#include <string>

#include "peak.hpp"
#include "peak_detection.hpp"


using namespace std;


PeakDetection::PeakDetection(map<string, string> config)
{
_threshold = stof(config["_threshold"]);
}

vector<Peak> PeakDetection::getPeaks(vector<float> &data){

Peak peak1 = Peak(10,1);
Peak peak2 = Peak(20,2);

vector<Peak> test;
test.push_back(peak1);
test.push_back(peak2);

return test;
}

峰值.hpp

#ifndef PEAK_H
#define PEAK_H

class Peak {
public:
float freq;
float mag;

Peak() : freq(), mag() {}
Peak(float f, float m) : freq(f), mag(m) {}
};

#endif

peak_detection_.pyx

# distutils: language = c++
# distutils: sources = peak_detection.cpp

from libcpp.vector cimport vector
from libcpp.map cimport map
from libcpp.string cimport string

cdef extern from "peak.hpp":
cdef cppclass Peak:
Peak()

cdef class PyPeak:
cdef Peak *thisptr
def __cinit__(self):
self.thisptr = new Peak()
def __dealloc__(self):
del self.thisptr

cdef extern from "peak_detection.hpp":
cdef cppclass PeakDetection:
PeakDetection(map[string,string])
vector[Peak] getPeaks(vector[float])

cdef class PyPeakDetection:
cdef PeakDetection *thisptr
def __cinit__(self, map[string,string] config):
self.thisptr = new PeakDetection(config)
def __dealloc__(self):
del self.thisptr
def getPeaks(self, data):
return self.thisptr.getPeaks(data)

最佳答案

这里的问题是 cython 不知道如何自动将 C++ 对象 Peak 转换为 python 包装版本 PyPeak

getPeaks 返回的 Peak 实例复制到 PyPeak 实例列表中的版本是:

# distutils: language = c++
# distutils: sources = peak_detection.cpp

from libcpp.vector cimport vector
from libcpp.map cimport map
from libcpp.string cimport string

cdef extern from "peak.hpp":
cdef cppclass Peak:
Peak()
Peak(Peak &)
float freq, mag


cdef class PyPeak:
cdef Peak *thisptr

def __cinit__(self):
self.thisptr = new Peak()

def __dealloc__(self):
del self.thisptr

cdef copy(self, Peak &other):
del self.thisptr
self.thisptr = new Peak(other)

def __repr__(self):
return "<Peak: freq={0}, mag={1}>".format(self.freq, self.mag)

property freq:
def __get__(self): return self.thisptr.freq
def __set__(self, freq): self.thisptr.freq = freq

property mag:
def __get__(self): return self.thisptr.mag
def __set__(self, mag): self.thisptr.mag = mag


cdef extern from "peak_detection.hpp":
cdef cppclass PeakDetection:
PeakDetection(map[string,string])
vector[Peak] getPeaks(vector[float])

cdef class PyPeakDetection:
cdef PeakDetection *thisptr

def __cinit__(self, map[string,string] config):
self.thisptr = new PeakDetection(config)

def __dealloc__(self):
del self.thisptr

def getPeaks(self, data):
cdef Peak peak
cdef PyPeak new_peak
cdef vector[Peak] peaks = self.thisptr.getPeaks(data)

retval = []

for peak in peaks:
new_peak = PyPeak()
new_peak.copy(peak)
retval.append(new_peak)

return retval

编译并运行后,我们得到了预期的输出:

In [1]: import peak_detection_

In [2]: print peak_detection_.PyPeakDetection({"_threshold" : "0.01"}).getPeaks([1,2,3])
[<Peak: freq=10.0, mag=1.0>, <Peak: freq=20.0, mag=2.0>]

关于python - 如何使用 Cython 公开将 C++ 对象返回给 Python 的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33573038/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com