在扩展中使用 PyModule_AddIntConstant()

问题描述 投票:0回答:1

我已经看到将带有十六进制值的符号常量添加到Python扩展模块并且我正在尝试重现这种效果:

#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�7\WDExpress\VC\Tools\MSVC .14.26428 in\HostX86\x86\link.exe”失败,退出状态为 1104

如何将

DEFINED
值添加到我的扩展中(以便我可以运行
utilities.DEFINED
)?

编辑:

正如下面的答案中提到的,关闭所有内容并再次尝试成功构建扩展,但是使用

return PyModule_Create(&value);
仍然会崩溃。

python c python-3.x python-c-api
1个回答
2
投票

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

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

  • 关闭每个正在运行的导入模块的解释器(以“解锁”WinUtils.cp36-win32.pyd

  • 构建(这一次,链接器将能够覆盖文件)

  • 测试(运行您的Python代码)

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

更新#0(关于第2nd问题):

正如我在我的评论之一中指定的,使用 PyModule_Create (根据 [Python.Docs]: PyObject* PyModule_New(const char *name),你会得到 未定义的行为):

PyMODINIT_FUNC PyInit_utilities()
{
    PyObject *mod = PyModule_Create(&func);
    PyModule_AddIntConstant(mod, "DEFINED", AF_INET);
    return mod;
}
© www.soinside.com 2019 - 2024. All rights reserved.