【问题标题】:C code crashes attempting Python remote procedure call via xmlrpcC 代码在尝试通过 xmlrpc 调用 Python 远程过程时崩溃
【发布时间】:2011-03-30 22:47:17
【问题描述】:

我正在尝试创建 C 代码来创建 Python xmlrpc 客户端并调用 xmlrpc 服务器上的方法(我正在考虑将其用作挂钩 DLL 的 IPC)。

这是代码...在它起作用之前,我不会对引用计数进行分层。

#include <Python.h>
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

static PyObject *xmlrpc_server_proxy = NULL;
static PyObject *set_server_proxy(void);
static void say_hi(void);

int main()
{
    xmlrpc_server_proxy = set_server_proxy();
    say_hi();
    return 0;
}

static PyObject *
set_server_proxy()
{
        PyObject *xmlrpc_client_mod, *xmlrpc_server_proxy_class, *location, *args;
        PyObject *result;
        Py_Initialize();
        xmlrpc_client_mod = PyImport_ImportModule("xmlrpc.client");
        xmlrpc_server_proxy_class = PyObject_GetAttrString(xmlrpc_client_mod, "ServerProxy");
        location = PyUnicode_FromString("http://127.0.0.1:8000/");
        args = Py_BuildValue("(O)", location);
        result = PyObject_CallObject(xmlrpc_server_proxy_class, args);
        Py_Finalize();
        return result;
}

static void say_hi()
{
    PyObject_CallMethod(xmlrpc_server_proxy, "say_hi", "()");
}

我已确认我的 Python xmlrpc 服务器在从另一个 Python 服务器代理调用时工作正常。当我尝试运行上述可执行文件时,它在PyObject_CallMethod() 上崩溃。为什么?

【问题讨论】:

  • 我最初的直觉是 PyObject_CallObject() 或 set_server_proxy() 中的 Py* 函数之一正在调用返回 NULL。您应该检查每个 Py* 函数的返回值,以查看返回 NULL 的内容,因为它可能会帮助您了解错误地调用函数。

标签: python c python-extensions


【解决方案1】:

在set_server_proxy() 的末尾附近,您正在调用Py_Finalize(),这会破坏解释器,随后您正在调用say_hi(),它假定解释器仍然存在。当 Python 解释器代码尝试引发错误时,PyErr_Occurred() 函数获取指向当前线程状态的指针,即NULL;它取消引用它,这会产生段错误。

将您的解释器初始化调用移动到 main() 函数中:

int main()
{
    Py_Initialize();
    xmlrpc_server_proxy = set_server_proxy();
    say_hi();
    Py_Finalize();
    return 0;
}

其次,如果您尝试使用 Python 的标准 xmlrpclib.ServerProxy,您可能需要将导入更改为:

xmlrpc_client_mod = PyImport_ImportModule("xmlrpclib");

【讨论】:

  • 是否有另一种方法可以使用解释器创建一个在解释器消失后仍然存在的 Python 对象?鉴于这将在钩子 DLL 中实现,我不确定是否可以将 Py_Initialize 移出被调用函数(除非它可以进入 Dllmain,我不确定它是否可以)。
  • 我认为这在绝大多数情况下是不可能的(也许在某些边缘情况下)。 PyObject_CallMethod 在内部调用其他直接依赖于解释器状态的函数。也许您可以将解释器的生命周期与 DllMain DLL_PROCESS_ATTACH / DLL_PROCESS_DETACH 事件联系起来?
  • 将 Py_Initialize 和 set_server_proxy() 移动到 DLL_PROCESS_ATTACH 和 Py_Finalize 到 DLL_PROCESS_DETACH 似乎可以工作......现在使用 xmlrpc 来监控 Vista Windows API 调用,而无需处理任何 UAC。感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 2017-03-20
  • 1970-01-01
  • 2020-10-16
  • 1970-01-01
  • 2017-05-12
  • 2015-07-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多