我可以將C++ enum
作爲真實實體而不是一組常量公開給SWIG,以便我可以在Python代碼中枚舉它們?如何使用SWIG枚舉枚舉成員
回答
我面臨同樣的問題。我希望SWIG很快支持C++ 11的enum class
。
下面是說服夜風把枚舉結構中的一個黑客:
#ifdef SWIG
%rename(MyEnum) MyEnumNS;
#endif
struct MyEnumNS
{
enum Value { Value1, Value2, Value3 };
};
typedef MyEnumNS::Value MyEnum;
在.cpp
代碼,你現在必須使用MyEnum::Value1
和Python代碼是MyEnum.Value1
。雖然令人費解,但typedef
可以防止必須更改在任何地方使用枚舉的現有代碼,並且SWIG%重命名使枚舉在SWIG包裝器中具有相同的名稱。
在Python中,你可以用一點代碼枚舉值:
def values(enum):
return [(k,v) for k,v in vars(enum).items() if isinstance(v,int)]
這不是漂亮,我喜歡看到一個更好的解決方案。
我敢肯定,你要找的是...
typemaps:由於類型的處理是如此重要的包裝代碼生成,SWIG使得它能夠被用戶完全定義(或重定義)。爲此,使用特殊的%typemap指令。 (SWIG Doc2.0)
對於您可能需要的有關typemaps的所有信息,請參閱SWIG文檔的鏈接。 http://www.swig.org/Doc2.0/Typemaps.html#Typemaps_nn2
Typemaps應該允許您告訴SWIG將C++枚舉轉換爲您想要的python對象。
@Flexo,tbh,我不知道類型圖,我是SWIG的新手,他們只是在項目的一些較暗的部分使用它,它工作,沒有人關心,但後來我決定擴展它位。 – unkulunkulu
我們可以做一些讓你在Python中枚舉的東西,相對較少入侵它所包裝的C++頭文件。例如,如果我們有一個頭文件:
#ifndef PYTHON_ENUM
#define PYTHON_ENUM(x) enum x
#endif
PYTHON_ENUM(TestName) {
foo=1,
bar=2
};
PYTHON_ENUM(SomeOtherName) {
woof,
moo
};
它擴展到只是在C++中常規的枚舉,但足以作爲一個頭文件暴露在Python枚舉成員。
使用%typemap(constcode)
我們可以在我們的Python模塊中爲enum注入一些額外的東西,但我們需要知道枚舉的名稱來完成此操作; SWIG typeinfo對象就好像它是一個int
。因此,我們在我們的PYTHON_ENUM
宏中使用了一些黑客技術來將枚舉的名稱存儲在自定義的類型映射中。
%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"
這將在每個具有鍵/值對的枚舉的中間模塊中創建一個PyDict。還有一些%pythoncode
粘合劑將中間模塊中的PyDict綁定到暴露的模塊中。 (我不知道如何通過名稱引用中間模塊,除了硬編碼爲_test - 根據需要更改)。
這是足夠的,我就可以使用它作爲:
Python 2.7.3 (default, Aug 1 2012, 05:16:07)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import test
>>> print test.SomeOtherName
{'woof': 0, 'moo': 1}
>>> print test.TestName
{'foo': 1, 'bar': 2}
>>>
所以看起來這很難,因爲SWIG的目的很簡單,似乎他們沒有考慮將C/C++反射帶入腳本語言,只是界面生成。看起來我不得不採用Mark Tolonen的解決方案,因爲很少有人會理解你的,儘管我現在正在理解它:D謝謝你嘗試使用類型映射的例子。 – unkulunkulu
@unkulunkulu - 通常SWIG會盡力讓您在C(或C++)中儘可能做到儘可能簡單,但除此之外,這往往會更困難。 – Flexo
@Flexo尼斯解決方案。我擴展了一下導入一個字典,它支持鍵完成,並用'x = dotdict(_test.x)'替換'x = _test.x'並添加了一個'%pythoncode%{from dicts import dotdict% }在'PYTHON_ENUM'宏之前。 –
- 1. 枚舉成員
- 2. 如何從枚舉成員
- 3. Jave枚舉成員
- 4. Python枚舉類成員
- 5. 枚舉結構的成員?
- 6. 枚舉和指向成員
- 7. 查找未使用的枚舉成員
- 8. 使用列枚舉的LINQ表枚舉
- 9. 如何在保持枚舉枚舉
- 10. #define枚舉或如何擴展枚舉
- 11. 如何枚舉嵌套枚舉器
- 12. 如何枚舉Objective-C中的枚舉?
- 13. 生成枚舉
- 14. 使用枚舉
- 15. 使用枚舉
- 16. 使用枚舉
- 17. 使用枚舉
- 18. 轉換枚舉來枚舉
- 19. 枚舉的枚舉[JAVA]
- 20. 帶枚舉的MySQL枚舉
- 21. Java類枚舉枚舉類
- 22. 重新枚舉枚舉
- 23. Java枚舉找到枚舉
- 24. 在枚舉中枚舉
- 25. 使用JavaPoet生成枚舉
- 26. 如何在枚舉類型中定義枚舉成員的映射?
- 27. 任何方式來枚舉類成員?
- 28. 如何使用枚舉值?
- 29. 如何使用枚舉?
- 30. 如何使用枚舉? java
是啊,我在想這樣的事情,但你的答案提供了一些準備使用的圖案,謝謝。你能解釋一下上面提到的'sizeof'問題嗎?什麼代碼可以完全打破,因爲我不太明白。 – unkulunkulu
我將刪除該部分。這是我在試圖找到實現時正在考慮的事情,但我只是重新訪問它,並不是一個真正的問題。 –