Python 在返回 C++ 映射值时崩溃
Posted
技术标签:
【中文标题】Python 在返回 C++ 映射值时崩溃【英文标题】:Python crashes on returning an C++ map value 【发布时间】:2018-06-26 11:37:00 【问题描述】:我正在编写一个测试以将数据保存在 C++ 映射中。我正在使用 Python C-Api。 添加 int 值并获取地图的长度是没有问题的。 但是,当我从地图中获取一个值并想要将其返回给 Python 时,解释器就会崩溃。 这是我的代码:
//some includes
int VerboseLog = 99;
typedef map<const char*, int> SessionKeeper;
static SessionKeeper openSessions;
static PyObject* getSession(PyObject* self, PyObject* args)
cout << "get" << endl;
const char *key;
if (!PyArg_ParseTuple(args, "z*", &key))
PyErr_SetString(PyExc_Exception, "UUID konnte nicht ausgelesen werden");
PyErr_PrintEx(1);
return NULL;
int r = openSessions.at(key);
return Py_BuildValue("i", r);
static PyObject *addSession(PyObject* self, PyObject* args)
cout << "Hello" << endl;
const char *key;
int toAppend;
if (!PyArg_ParseTuple(args, "si", &key, &toAppend))
PyErr_SetString(PyExc_Exception, "Ein Parameter konnte nicht ausgelesen werden");
PyErr_PrintEx(1);
return NULL;
openSessions[key] = toAppend;
cout << openSessions.size() << endl;
cout << openSessions[key] << endl;
Py_RETURN_NONE;
static PyObject* length(PyObject *self)
cout << "length: ";
int i = openSessions.size();
return Py_BuildValue("i",i);
static PyMethodDef SessionKeeper_methods[] =
/*Note the third entry (METH_VARARGS). This is a flag telling the interpreter the calling convention
to be used for the C function. It should normally always be METH_VARARGS or METH_VARARGS | METH_KEYWORDS;
a value of 0 means that an obsolete variant of PyArg_ParseTuple() is used.*/
"length", (PyCFunction)length, METH_VARARGS, "return length of a Session" ,
"addSession", (PyCFunction)addSession, METH_VARARGS, "add a Session." ,
"getSession", (PyCFunction)getSession, METH_VARARGS, "get a Session" ,
NULL
;
static PyModuleDef sessionKeeperMod =
PyModuleDef_HEAD_INIT,
u8"SessionKeeper",
NULL,
-1,
SessionKeeper_methods
;
static PyModuleDef CpluplusModules_ModDef =
PyModuleDef_HEAD_INIT,
u8"CPlusPlusMouldes",
u8"Enthält alle Erweietrungen",
-1,
NULL, NULL, NULL, NULL, NULL
;
PyMODINIT_FUNC PyInit_CPlusPlusModules(void)
PyObject* m, *sessionMod;
if (PyType_Ready(&TAModulType) < 0)
return NULL;
if (PyType_Ready(&DatabaseReader_Type) < 0)
return NULL;
if (!(sessionMod = PyModule_Create(&sessionKeeperMod)))
cout << "fail" << endl;
return NULL;
m = PyModule_Create(&CpluplusModules_ModDef);
if (m == NULL)
return NULL;
Py_INCREF(&TAModulType);
Py_INCREF(&DatabaseReader_Type);
PyModule_AddObject(m, "TAModul", (PyObject *)&TAModulType);
PyModule_AddObject(m, "DBReader", (PyObject *)&DatabaseReader_Type);
PyModule_AddObject(m, "SessionKeeper", sessionMod);
return m;
其他模块(DBReader 和 TAModule)工作正常。目标是保护地图中的 PythonObjects(包含 DbReader 对象和 TAModul 对象)。
但是回到我的问题,为什么 getSession 在返回时会使解释器崩溃?以及为什么长度函数可以正常工作。
【问题讨论】:
【参考方案1】:map<const char*,...>
将 match based on the address of the string rather than the contents。因此,at
很可能会失败并抛出 C++ out_of_range
异常。
你应该从换行开始
int r = openSessions.at(key);
使用 try catch
块,阻止 out_of_range
异常通过 Python 解释器(不是 C++,因此无法处理)传播。
然后您应该更改映射以匹配字符串内容上的键。最简单的方法是使用map<std::string,int>
。
【讨论】:
谢谢这是问题的一部分,我还不得不在解析函数中使用“z*”的“s”状态以上是关于Python 在返回 C++ 映射值时崩溃的主要内容,如果未能解决你的问题,请参考以下文章
Obj-C 框架返回 nil,并让我的 Swift 代码崩溃,说“致命错误:在展开可选值时意外发现 nil”
Obj-C 框架返回 nil,并让我的 Swift 代码崩溃,说“致命错误:在展开可选值时意外发现 nil”