【问题标题】:Using PyModule_AddIntConstant() in an extension在扩展中使用 PyModule_AddIntConstant()
【发布时间】:2018-11-23 15:12:49
【问题描述】:

我见过Adding symbolic constants with hex values to Python extension module,我正在尝试重现这种效果:

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

static PyObject * sys_shutdown(PyObject *self, PyObject *args) {
    int val;

    if (!PyArg_ParseTuple(args, "i", &val))
        val = SHTDN_REASON_MINOR_OTHER; // Provide failsafe

    ExitWindowsEx(EWX_POWEROFF, val); // Shutdown
    return Py_BuildValue("");
}

static PyObject * sys_restart(PyObject *self, PyObject *args) {
    int val;

    if (!PyArg_ParseTuple(args, "i", &val))
        val = SHTDN_REASON_MINOR_OTHER; // Provide failsafe
    ExitWindowsEx(EWX_REBOOT, val); // Restart
    return Py_BuildValue("");
}

static PyObject * sys_log_out(PyObject *self, PyObject *args) {
    int val;

    if (!PyArg_ParseTuple(args, "i", &val))
        val = SHTDN_REASON_MINOR_OTHER; // Provide failsafe

    ExitWindowsEx(EWX_LOGOFF, val); // Log out
    return Py_BuildValue("");
}

static PyMethodDef localMethods[] = {
    {"shutdown", (PyCFunction)sys_shutdown, METH_VARARGS, "..."},
    {"restart", (PyCFunction)sys_restart, METH_VARARGS, "..."},
    {"log_out", (PyCFunction)sys_log_out, METH_VARARGS, "..."},
    {NULL, NULL, 0, NULL}
};

static struct PyModuleDef func = {
    PyModuleDef_HEAD_INIT,
    "utilities",
    "...",
    -1,
    localMethods,
};

PyMODINIT_FUNC PyInit_utilities(void) {
    PyObject *value;

    value = PyModule_New(&func);

    PyModule_AddIntConstant(value, "DEFINED", AF_INET);

    return PyModule_Create(&func);
}

设置脚本:

from distutils.core import setup, Extension

module = Extension(
    "utilities", 
    sources = ["main.c"],
        libraries = ["user32"]
)

setup (
    name = "Utilities",
    version = "1.0",
    ext_modules = [module])

一切都按预期构建,但是我不能在我的扩展中使用DEFINED

import utilities
for i in utilities.__dict__: print(i)
utilities.DEFINED # AttributeError: module 'utilities' has no attribute 'DEFINED'

返回:

__name__
__doc__
__package__
__loader__
__spec__
shutdown
restart
log_out
__file__

我想像这样返回value

return PyModule_Create(&value);

但是返回:

LINK : 致命错误 LNK1104: 无法打开文件 'build\lib.win32-3.6\WinUtils.cp36-win32.pyd' 错误:命令 'C:\Program Files (x86)\Microsoft Visual Studio\2017\WDExpress\VC\Tools\MSVC\14.14.26428\bin\HostX86\x86\link.exe' 失败,退出状态为 1104

如何将DEFINED 值添加到我的扩展程序(以便我可以运行utilities.DEFINED)?

编辑:

正如下面的答案中提到的,关闭所有内容并再次尝试成功构建扩展,但是使用return PyModule_Create(&amp;value); 仍然崩溃。

【问题讨论】:

    标签: python c python-3.x python-c-api


    【解决方案1】:

    PyModule_AddIntConstant(value, "DEFINED", DEFINED_VALUE); 是正确的(假设 DEFINED_VALUE 是 (C) long)。

    加上最后的链接器错误(以及您正在编写代码然后进行测试的事实,等等......)告诉我链接器无法编写新的。 pyd 文件(包含最新更改 - 包括 DEFINED 变量),因为它正在由之前启动的导入您的模块的 python.exe 进程使用。

    • 关闭每个导入您的模块的正在运行的解释器(以“解锁”WinUtils.cp36-win32.pyd
    • 构建(这一次,链接器将能够覆盖文件)
    • 测试(运行您的 Python 代码)

    注意:您可以检查函数返回值([Python]: int PyModule_AddIntConstant(PyObject *module, const char *name, long value))。

    @EDIT0(关于第 2nd 问题):

    正如我在我的一个 cmets 中指定的那样,使用 PyModule_Create(根据 [Python]: PyObject* PyModule_New(const char *name),你会得到未定义的行为):

    PyMODINIT_FUNC PyInit_utilities() {
        PyObject *mod = PyModule_Create(&func);
        PyModule_AddIntConstant(mod, "DEFINED", AF_INET);
        return mod;
    }
    

    【讨论】:

    • 你是对的,它构建了代码,但解释器仍然崩溃。我将编辑我的帖子以使其更具可重复性。
    • 崩溃”是指NameError?
    • 没有。我的意思是解释器会立即打开并关闭(我添加了input(),所以我知道出了点问题)。如果我从 IDLE 运行它,Shell 会出现。很遗憾,没有错误。
    • 只有当您访问DEFINED 时?也试试其他成员 (restart)。无论如何PyModule_NewPyModule_Create 对我来说似乎不对。试试return value;(并初始化value = PyModule_Create(&amp;func);)。
    • 应该是这样。注意 Utilities 与 utilities(包括在您的 setup.py 中)。都应该匹配。 spammethods 也应该以 {NULL, NULL, 0, NULL} 结尾。但无论如何我很困惑,在这个问题中有一些代码是有效的。发布问题后不要更改它(或者如果您确实相应地调整了问题)。
    猜你喜欢
    • 2017-07-23
    • 1970-01-01
    • 1970-01-01
    • 2021-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-05
    • 2011-03-10
    相关资源
    最近更新 更多