C++ 嵌入式 Python PyBytes_AsString 导致 DLL 崩溃
Posted
技术标签:
【中文标题】C++ 嵌入式 Python PyBytes_AsString 导致 DLL 崩溃【英文标题】:C++ embedded Python PyBytes_AsString causing DLL to crash 【发布时间】:2014-12-19 19:00:14 【问题描述】:试图让 C++ 和 Python 嵌入式 DLL 工作,但它似乎遇到了 PyBytes_AsString 组件。
特别是这一行:
strcpy(buffer, PyBytes_AsString(pValue));
它试图将 milp_closest.solve 函数 int 的返回值复制到 char 缓冲区。但它使 DLL 崩溃,几乎就像它们是不兼容的类型一样。
输入格式 - milp_closest.solve(10, 20, 30, 25)
输出字符串格式 - (0, 1, 25.0, [1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1 ])
// The Function calls a Python module named milp_closest()
// Input parameters: 4 integers
// Output parameters: a string return by the call to the Python module
extern "C" LPCSTR __declspec( dllexport ) __stdcall TS2Py_Milp(int n, int p1, int p2, int average)
static char buffer[256]="";
PyObject *pName, *pModule, *pDict, *pfSolve;
PyObject *pArgs, *pValue;
Py_Initialize();
//pName = PyString_FromString("");
/* Error checking of pName left out */
pModule = PyImport_ImportModule("milp_closest"); // which Python module do we wish to load
//Py_DECREF(pName);
if (pModule != NULL)
pfSolve = PyObject_GetAttrString(pModule, "solve"); // which function in the above-loaded module, do we wish use
/* pfSolve is a new reference */
if (pfSolve && PyCallable_Check(pfSolve))
pArgs = PyTuple_New(4); //The Solve funciton takes 4 input parameters
pValue = PyLong_FromLong((long) n); // store 1st parameter (n) for function Solve
/* pValue reference stolen here: */
PyTuple_SetItem(pArgs, 0, pValue);
pValue = PyLong_FromLong((long) p1); // store 1st parameter (n) for function Solve
PyTuple_SetItem(pArgs, 1, pValue);
pValue = PyLong_FromLong((long) p2); // store 1st parameter (n) for function Solve
PyTuple_SetItem(pArgs, 2, pValue);
pValue = PyLong_FromLong((long) average); // store 1st parameter (n) for function Solve
PyTuple_SetItem(pArgs, 3, pValue);
pValue = PyObject_CallObject(pfSolve, pArgs); // call the Python funciton "Solve"
Py_DECREF(pArgs);
if (pValue != NULL)
strcpy(buffer, PyBytes_AsString(pValue));// copy the RERTURN value(string) form Python function call, in to our return value
Py_DECREF(pValue);
else
Py_DECREF(pfSolve);
Py_DECREF(pModule);
PyErr_Print();
fprintf(stderr,"Call failed\n");
return "call to function solve() failed";
else
if (PyErr_Occurred())
PyErr_Print();
fprintf(stderr, "Cannot find function \"solve\"\n" );
Py_XDECREF(pfSolve);
Py_DECREF(pModule);
else
PyErr_Print();
fprintf(stderr, "Failed to load \"milp_closest.py\"\n");
return "Failed to laod module <milp_closest.py>";
Py_Finalize();
// we return (or pass on) the string returned from the call to the Python function "solve".
return (LPCSTR) buffer;
关于我可能出错的地方有什么建议吗?
【问题讨论】:
【参考方案1】:第一,确保您知道导致崩溃的确切行(使用打印语句或通过调试器)。这将确保我们正在调试正确的区域。另外,尝试打印从 PyBytes_AsString() 返回的 char*。
其次,您将一个元组传递给 milp_closest.solve()
函数,但您的示例传递了 4 个整数。我想你的意思是这个?
PyObject* args = Py_BuildValue("llll", 10, 20, 30, 25);
if (!*args)
/* handle error */
Py_Object* pValue = PyObject_CallObject(pfSolve, args);
【讨论】:
仅供参考 - 更新了原始帖子以显示特定的兴趣线。我也在进一步调查您的第二条评论。 返回值的长度呢?您可能会返回超过 256 个字节,这会导致您 strcpy 被覆盖。尝试使用 strncpy() 代替。以上是关于C++ 嵌入式 Python PyBytes_AsString 导致 DLL 崩溃的主要内容,如果未能解决你的问题,请参考以下文章
在 C++ 中扩展嵌入式 Python - 设计与 C++ 实例交互