函数调用时的 PyObject 段错误
PyObject segfault on function call
我正在尝试使用 Python 打开一个对话框以接受输入到我的C++应用程序中。
这是我正在尝试做的事情的非常小的表示:
#include <iostream>
#include <Python.h>
int main()
{
/* Begin Python Ititialization - only needs to be done once. */
PyObject *ip_module_name = NULL;
PyObject *ip_module = NULL;
PyObject *ip_module_contents = NULL;
PyObject *ip_module_getip_func = NULL;
Py_Initialize();
PyEval_InitThreads();
ip_module_name = PyString_FromString( "get_ip" );
ip_module = PyImport_Import( ip_module_name );
ip_module_contents = PyModule_GetDict( ip_module );
ip_module_getip_func = PyDict_GetItemString( ip_module_contents, "get_ip_address" );
/* End Initialization */
PyGILState_STATE state = PyGILState_Ensure();
PyObject *result = PyObject_CallObject( ip_module_getip_func, NULL );
if( result == Py_None )
printf( "Nonen" );
else
printf( "%sn", PyString_AsString( result ) );
PyGILState_Release( state );
/* This is called when the progam exits. */
Py_Finalize();
}
但是,当我使用 PyObject_CallObject 调用函数时,应用程序会出现段错误。我猜这是因为我正在使用 Tk 库。我尝试将我的应用程序链接到_tkinter.lib,tk85.lib,tcl85.lib,tkstub85.lib,tclstub85.lib,但这些都无济于事。我很困惑...
下面是脚本:
import Tkinter as tk
from tkSimpleDialog import askstring
from tkMessageBox import showerror
def get_ip_address():
root = tk.Tk()
root.withdraw()
ip = askstring( 'Server Address', 'Enter IP:' )
if ip is None:
return None
ip = ip.strip()
if ip is '':
showerror( 'Error', 'Please enter a valid IP address' )
return get_ip_address()
if len(ip.split(".")) is not 4:
showerror( 'Error', 'Please enter a valid IP address' )
return get_ip_address()
for octlet in ip.split("."):
x = 0
if octlet.isdigit():
x = int(octlet)
else:
showerror( 'Error', 'Please enter a valid IP address' )
return get_ip_address()
if not ( x < 256 and x >= 0 ):
showerror( 'Error', 'Please enter a valid IP address' )
return get_ip_address()
return ip
编辑:添加了我的线程设置
添加PySys_SetArgv(argc, argv)
(以及int argc, char **argv
参数到main
(,您的代码就可以工作了。
tk.Tk()
访问sys.argv
,除非PySys_SetArgv
被调用,否则不存在。这会导致一个异常,该异常被传播出get_ip
并通过返回NULL
PyObject_CallObject
报告给 Python/C 。NULL
被存储到result
并传递给PyString_AsString
,这是观察到的崩溃的直接原因。
关于代码的几点评论:
-
调试它需要付出努力,因为代码不进行任何错误检查,它会盲目地向前按,直到由于传递 NULL 指针而崩溃。至少可以做的是写这样的东西:
if (!ip_module_name) { PyErr_Print(); exit(1); } // and so on for every PyObject* that you get from a Python API call
在实际代码中,您不会
exit()
,但会执行一些清理并返回NULL
(或引发C++级异常,或任何合适的内容(。 -
无需在已知包含 GIL 的线程中调用
PyGILState_Ensure
。正如PyEval_InitThreads
的文档所述,它初始化 GIL 并获取它。当从 C 回调调用 Python 时,你只需要重新获取 GIL,该回调来自与 Python 无关的工具包事件循环。 -
从 Python 收到的新引用需要
Py_DECREF
一次不再需要。为了简洁起见,可以从最小示例中省略引用计数,但应始终注意。
- 为什么PyImport_ImportModule python 3.7.2 中出现段错误?
- 为什么在访问 vtkRenderWindow 的"交互器"变量时会发生段错误?
- 全局向量导致 C++ 程序结束时出现段错误
- 为什么重载运算符<<打印特征类成员会导致段错误?
- 更改条件段错误
- 使用 TTF_RenderText() 加载字体时获取段错误 TTF_OpenFontRW()
- 注册对对象工厂的调用会导致段错误
- pthread_create在构造函数段错误中
- Nanoflann发现邻居提出段错误
- C++ 中的构造函数、继承、堆栈、堆、this-pointer 和段错误
- 具有unique_ptr的 CRTP 会导致段错误
- 增强纤维work_stealing屏障会导致段错误
- 当我返回指向结构的指针向量时出现段错误
- C++为什么我的代码没有爆炸/段错误?
- Pthread段错误,使用指向main中变量的指针
- C++ 模板中的段错误
- 相当于Windows/MSVC上的段错误?
- 为什么我的 LLVM JIT 实现出现段错误?
- 为什么访问我的引用捕获变量会导致我的 lambda 函数出现段错误?
- 为什么自删除的全局 Vulkan 实例仅在添加层时才导致段错误?