已解决:需要py::return_value_policy::reference
由于某种原因似乎找不到该功能:
>>> import kaldi_rw
>>> reader = kaldi_rw.Pykread("/path/to/file")
>>> m=reader.get()
Segmentation fault (core dumped)
但是!
>>> import kaldi_rw
>>> reader = kaldi_rw.Pykread("/path/to/file")
>>> reader.close()
True
>>> reader = kaldi_rw.Pykread("/path/to/file")
>>> m = reader.get() # works!
HERE
>>>reader.close()
True
>>>
由于某种原因,仅在第二种情况下,才调用正确的功能(事实证明是打印了“ HERE”。我不知道发生了什么。
源代码:
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include "util/common-utils.h"
#include "matrix/kaldi-matrix.h"
#include "base/kaldi-common.h"
#include <iostream>
namespace py=pybind11;
using namespace kaldi;
class Pykread {
public:
Pykread(const std::string fpath): obj(fpath) {
ptr = nullptr;
isdone = false;
}
py::array_t<float> get() {
std::cout<<"HERE\n";
if (obj.Done()) {
ptr = new float[1]();
isdone = true;
return py::array_t<float>(py::buffer_info(ptr, sizeof(float), py::format_descriptor<float>::format(), 1, {0}, {0}));
}
mat = &(obj.Value());
ptr = mat->Data();
int32_t numrows = mat->NumRows(), numcols = mat->NumCols();
return py::array_t<float>(py::buffer_info(ptr, sizeof(float), py::format_descriptor<float>::format(), 2,
{numrows, numcols}, {sizeof(float) * numrows, sizeof(float)}));
}
void next() {
obj.Next();
}
bool close() {
if (isdone) delete ptr;
return obj.Close();
}
SequentialBaseFloatMatrixReader obj;
float* ptr;
Matrix<BaseFloat>* mat;
bool isdone;
};
PYBIND11_MODULE(kaldi_rw, m) {
m.doc() = "pybind11 stuff";
py::class_<Pykread>(m, "Pykread")
.def(py::init<std::string>())
.def("get", &Pykread::get)
.def("next", &Pykread::next)
.def("close", &Pykread::close);
}
我不知道对close()
的呼叫会产生什么影响。
它要求我添加更多详细信息,但我不知道该说些什么,我正在使用的编译器标志为-O3 -Wall -shared -std=c++11
。
edit:通过添加py::scoped_ostream_redirect
,我得到一致的“ HERE”打印。仍然不知道为什么发生段错误。
edit2:尝试按照here的内容进行操作。从py::array_t
切换到使用什么都没做的py::capsule
进行初始化。这样做有帮助,但是在执行m
m=reader.get(); reader.next(); m=reader.get()
时仍然出现段错误