gpt4 book ai didi

python - Python 后续中的 SWIG 枚举创建

转载 作者:太空宇宙 更新时间:2023-11-04 13:16:22 24 4
gpt4 key购买 nike

研究如何使用 swig 在 Python 中很好地包装枚举,我遇到了 this回答。

我正在尝试创建这样的枚举:

#ifndef PYTHON_ENUM 
#define PYTHON_ENUM(x) enum x
#endif

PYTHON_ENUM(TestName) {
foo=1,
bar=2
};

PYTHON_ENUM(SomeOtherName) {
woof,
moo
};

我这样使用 .i 文件

%module test
%{
#include "test.h"
%}

%typemap(constcode) int {
PyObject *val = PyInt_FromLong(($type)($value));
SWIG_Python_SetConstant(d, "$1", val);
const char *name = "$typemap(enum_realname,$1_type)";
PyObject *e = PyDict_GetItemString(d, name);
if (!e) PyDict_SetItemString(d, name, e = PyDict_New());
PyDict_SetItemString(e, "$value", val);
}
#define PYTHON_ENUM(x) \
%typemap(enum_realname) int "x"; \
%pythoncode %{ \
x = _test.x\
%} \
enum x

%include "test.h"

问题是这会抛出 AttributeError: module '_test' has no attribute 'TestName'这源于这样一个事实,即生成的 test.py 定义了 TestName 字典:

TestName = _test.testEnum       # This should be in the last line

_test.foo_swigconstant(_test)
foo = _test.foo

_test.bar_swigconstant(_test)
bar = _test.bar

在调用 TestName = _test.testEnum 时,_test 没有 testEnum 成员并抛出异常。一旦 foo_swigconstant()bar_swigconstant() 运行,就会生成 _test.testEnum 并且 TestName = _test.testEnum 不会失败。因此,这一行应该在枚举值注册之后。如果我手动执行它会起作用,但每次 SWIG 运行时我都必须这样做,这有点麻烦。其他枚举也是如此。我可以更改接口(interface)文件以适应这种情况吗?

最佳答案

我没有看到这个错误。我编译并链接示例如下:

swig3.0 -c++ -python test.i
g++ -c -fPIC test_wrap.cxx -I/usr/include/python2.7
g++ -shared -g test_wrap.o -o _test.so

然后它就完全按照 Flexo 的建议工作了。请注意,生成的 test.py 和 _test.so 位于同一目录中。我在 Debian 下使用 Python 2.7.6 和 SWIG 3.0.7。

我使用 VS2013 和 SWIG 3.0.8 进行了同样的尝试。发生的事情是 typemap(constcode) 生成函数 woof_swigconstant 等,而不是插入 const 代码,它只是暴露静态字典。您使用 SWIG 3.0.7 尝试过吗?

我对此进行了更深入的研究。使用 SWIG 3.0.8 和 VS2013。生成的代码例如foo 条目是:

SWIGINTERN PyObject *foo_swigconstant(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
PyObject *module;
PyObject *d;
if (!PyArg_ParseTuple(args,(char*)"O:swigconstant", &module)) return NULL;
d = PyModule_GetDict(module);
if (!d) return NULL;
{
PyObject *val = PyInt_FromLong((int)(foo));
SWIG_Python_SetConstant(d, "foo", val);
const char *name = "TestName";
PyObject *e = PyDict_GetItemString(d, name);
if (!e) PyDict_SetItemString(d, name, e = PyDict_New());
PyDict_SetItemString(e, "foo", val);
}
return SWIG_Py_Void();
}

至此,一个函数入口就生成了。在 Debian 上使用 SWIG 3.0.7 和 Python 2.7.6,我得到以下结果

  {
PyObject *val = PyInt_FromLong((int)(foo));
SWIG_Python_SetConstant(d, "foo", val);
const char *name = "TestName";
PyObject *e = PyDict_GetItemString(d, name);
if (!e) PyDict_SetItemString(d, name, e = PyDict_New());
PyDict_SetItemString(e, "foo", val);
}

SWIG_InstallConstants(d,swig_const_table); 之后立即插入。我相信从 SWIG 3.0.7 到 3.0.8 发生了一些变化。

关于python - Python 后续中的 SWIG 枚举创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37141526/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com