llu*_*lpu 5 c++ enums swig python-3.x
编辑:这个答案解决了问题,但最后我提出了一个更加模块化的解决方案。一探究竟 :)
我从两次 讨论中知道,为了类型安全,enum class应该选择哪个。enum出于这个原因,我在我的项目中使用它,但是当用 SWIG 包装它们时,我得到了一些我不太喜欢的东西。
给出简单的枚举
enum class type {
A, B, C, D, E, F, G, H, I
};
Run Code Online (Sandbox Code Playgroud)
在一个.hpp文件中,比如说my_types.hpp,并且该my_types.i文件:
%module my_types
%{
#include "my_types.hpp"
%}
%include "my_types.hpp"
Run Code Online (Sandbox Code Playgroud)
生成的python文件包含包含
type_A = _my_types.type_A
type_B = _my_types.type_B
type_C = _my_types.type_C
type_D = _my_types.type_D
type_E = _my_types.type_E
type_F = _my_types.type_F
type_G = _my_types.type_G
type_H = _my_types.type_H
type_I = _my_types.type_I
Run Code Online (Sandbox Code Playgroud)
这意味着当在Python中使用它时我必须这样做
import my_types as mt
mt.type_A
Run Code Online (Sandbox Code Playgroud)
使用它们,这......好吧,在这种情况下还可以,因为这个词type不是那么长,但是对于更长的词来说,它看起来不太好,而且,对我来说,它也不会让在每个枚举值的开头添加枚举名称很有意义。
有什么方法可以重命名它们(也许使用%rename)以便使用它们可以像这样简单?
import my_types as mt
mt.A
Run Code Online (Sandbox Code Playgroud)
我不知道%rename在这种情况下如何使用,或者甚至可以用于此目的。任何帮助,包括如何以不同的方式做同样的事情(可能没有枚举)的想法,将不胜感激。谢谢你们。
编辑:一些评论指出,将枚举的名称放在每个枚举的名称前面确实有意义。我想详细说明为什么我(对我来说)不这样做。如果我们考虑与枚举调用相同的模块的情况,那么代码看起来有点多余。由于types它已经是Python的模块,所以更好的例子是颜色:
enum class colours {
Blue, Red
};
Run Code Online (Sandbox Code Playgroud)
并且将按照建议使用包装的代码,如下所示:
import colours
Blue = colours.colours_Blue
Red = colours.colours_Red
Run Code Online (Sandbox Code Playgroud)
在我看来,编写colours来引用Blue,Red是不必要的,因为该模块colours仅包含一个“枚举”。换成这个不是更好吗?
import colours
Blue = colours.Blue
Red = colours.Red
Run Code Online (Sandbox Code Playgroud)
答案已经解释了如何实现这一目标。我会尽快查看。多谢!
编辑:这个答案解决了问题。我想对其进行一些更改并提出一个稍微更“模块化”的解决方案:
%pythoncode %{
__enum_name = "colours" # your enumeration's name
__enum = __import__(__enum_name) # import module
__scope_name = __enum_name + "_" # scope's name (= "colours_")
__scope_length = len(__scope_name) # length
for name in dir(__enum):
if name.find(__scope_name) == 0:
setattr(__enum, name[__scope_length:], getattr(__enum, name))
delattr(__enum, name) # optional
del name, __enum_name, __enum, __scope_name, __scope_length
%}
Run Code Online (Sandbox Code Playgroud)
我认为这可以更轻松地复制和粘贴您拥有十分之一枚举的项目:)。再次,基于这个答案。
其次,我不完全理解为什么你想要删除作用域(尽管我猜这是因为在 python 中你已经获得了模块作用域,这是你在 C++ 中没有的)。现在,我认为无法%rename工作,因为它不是文本转换。不过,我可以想到两种选择,一种是用 C++ 重命名,另一种是用 Python 重命名。
改成my_types.hpp:
enum class type {
A, B, C, D, E, F, G, H, I
};
#ifdef SWIG
constexpr type A = type::A;
constexpr type B = type::B;
constexpr type C = type::C;
constexpr type D = type::D;
constexpr type E = type::E;
constexpr type F = type::F;
constexpr type G = type::G;
constexpr type H = type::H;
constexpr type I = type::I;
#endif
Run Code Online (Sandbox Code Playgroud)
并编译包装器并-DSWIG添加到命令行。
修改my_types.i为:
%module my_types
%{
#include "my_types.hpp"
%}
%include "my_types.hpp"
%pythoncode %{
import my_types
for name in dir(my_types):
if name.find('type_') == 0:
setattr(my_types, name[5:], getattr(my_types, name))
delattr(my_types, name) # optional
del name
%}
Run Code Online (Sandbox Code Playgroud)