Я создаю проект и хочу получить массив numpy в проекте C ++.Я могу получить правильные числа, но он сообщает о нарушении прав чтения.Вот мой код Python с именем main.py
import numpy as np
import tensorflow as tf
class PyInterface(object):
def __init__(self):
self.X = None
self.Y = None
def generate_np_uint8(self):
np_array = np.random.randint(low=0, high=255, size=(2,2,2),dtype=np.uint8);
print("Python, uint8:", np_array)
return np_array
def generate_np_float32(self):
np_array = np.random.rand(2,2,2).astype(np.float32)
print("Python, float:", np_array)
return np_array
if __name__ == '__main__':
py = PyInterface();
py.generate_np_uint8();
py.generate_np_float32();
Вот мой код C ++ для расширения Python
public:
float * CppPythonHandler::get_float() {
return generate_np_float32();
}
private:
float * CppPythonHandler::generate_np_float32() {
const int ND{3};
float *c_out = new float[8];
PyArrayObject *np_ret;
PyObject* np_array = PyObject_CallMethod(interface, (const char*)"generate_np_float32", NULL, NULL);
if (np_array) {
np_ret = reinterpret_cast<PyArrayObject*>(np_array);
if (PyArray_NDIM(np_ret) != ND) {
std::cout << "Function returned with wrong dimension" << std::endl;
Py_DECREF(np_array);
Py_DECREF(np_ret);
return c_out;
}
c_out[0] = *((float *)PyArray_GETPTR3(np_ret, 0, 0, 0));
c_out[1] = *((float *)PyArray_GETPTR3(np_ret, 0, 0, 1));
c_out[2] = *((float *)PyArray_GETPTR3(np_ret, 0, 1, 0));
c_out[3] = *((float *)PyArray_GETPTR3(np_ret, 0, 1, 1));
c_out[4] = *((float *)PyArray_GETPTR3(np_ret, 1, 0, 0));
c_out[5] = *((float *)PyArray_GETPTR3(np_ret, 1, 0, 1));
c_out[6] = *((float *)PyArray_GETPTR3(np_ret, 1, 1, 0));
c_out[7] = *((float *)PyArray_GETPTR3(np_ret, 1, 1, 1));
for (int i = 0; i < 8; ++i) {
std::cout << c_out[i] << " ";
}
std::cout << std::endl;
Py_DECREF(np_ret);
Py_DECREF(np_array);
return c_out;
}
else{
PyErr_Print();
Py_DECREF(np_array);
Py_DECREF(np_ret);
return c_out;
}
}
Вот мой main.cpp
static int numargs=0;
static PyObject*
emb_numargs(PyObject *self, PyObject *args)
{
if(!PyArg_ParseTuple(args, ":numargs"))
return NULL;
return PyLong_FromLong(numargs);
}
static PyMethodDef EmbMethods[] = {
{"numargs", emb_numargs, METH_VARARGS,
"Return the number of arguments received by the process."},
{NULL, NULL, 0, NULL}
};
static PyModuleDef EmbModule = {
PyModuleDef_HEAD_INIT, "emb", NULL, -1, EmbMethods,
NULL, NULL, NULL, NULL
};
static PyObject*
PyInit_emb(void)
{
return PyModule_Create(&EmbModule);
}
int main(int argc, char *argv[]) {
if (argc < 1) {
fprintf(stderr,"Usage: call pythonfile funcname [args]\n");
return 1;
}
numargs = argc;
PyImport_AppendInittab("emb", &PyInit_emb);
Py_Initialize(); // initialize python interpreter
PyRun_SimpleString("import sys");
PyRun_SimpleString("if not hasattr(sys, 'argv'):\n sys.argv=['']");
PyRun_SimpleString("sys.path.insert(0, \"./\")");
PyRun_SimpleString("sys.path.insert(0, \"./venv/Lib\")");
PyRun_SimpleString("sys.path.insert(0, \"./venv/Lib/site-packages\")");
// instance cpp interface object
CppPythonHandler * pInter = new CppPythonHandler("main", "PyInterface");
// unsigned char * np_uint8 = pInter->get_uint8();
float * np_float = pInter->get_float();
std::cout<<"End test"<<std::endl;
// delete []pInter;
if (Py_FinalizeEx() < 0) {
std::cout << "Fails to release" << std::endl;
return 120;
}
system("pause");
return 0;
}
По терминалу я вижу, что могу получить правильное значение из скрипта Python ![enter image description here](https://i.stack.imgur.com/72SY8.png)
из стека вызовов. Я знаю, что он искажается в PyObject_Alloc ![enter image description here](https://i.stack.imgur.com/7p8m8.png)
но я до сих пор не понимаю, в чем именно проблема.может кто-нибудь сказать мне
EDIT1 : Вот мой конструктор
CppPythonHandler::CppPythonHandler(const char* pModuleName, const char* pClassName) {
interfaceModule = NULL;
interfaceClass = NULL;
interface = NULL;
interfaceModule = PyImport_ImportModule(pModuleName);
if (interfaceModule == NULL) {
PyErr_Print();
fprintf(stderr,"Fails to import the module.\n");
Py_DECREF(interfaceModule);
}
else{
// import interface class
interfaceClass = PyObject_GetAttrString(interfaceModule, pClassName);
if (interfaceClass && PyCallable_Check(interfaceClass)) {
// NULL represents no args
interface = PyObject_CallObject(interfaceClass, NULL);
Py_DECREF(interfaceClass);
Py_DECREF(interfaceModule);
if(interface == NULL){
fprintf(stderr,"Fails to instance interface.\n");
Py_DECREF(interface);
}
std::cout<<"Initailization done"<<std::endl;
}
else{
if (PyErr_Occurred())
PyErr_Print();
fprintf(stderr,"Fails to import the class.\n");
Py_DECREF(interfaceClass);
Py_DECREF(interfaceModule);
}
}
}
interfaceModule, interfaceClass и интерфейс являются частными PyObject *
EDIT2: вот локальные параметры PyObject_Alloc ![enter image description here](https://i.stack.imgur.com/XuBAY.png)