2016-05-10 4 views
1

swigを使用してPythonでenumをうまくラップする方法を調べると、私はthisの答えに出くわしました。SWIGの列挙型をPythonのフォローアップで作成

私はそのような列挙型を作成しようとしています:モジュールの_test 'には属性がありません:

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

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

PYTHON_ENUM(SomeOtherName) { 
    woof, 
    moo 
}; 

は、私はこの問題は、これははAttributeErrorをスローすることをあること

%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" 

などの.iファイルを使用します'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が失敗しません。したがって、この行はenum値の登録後に行かなければなりません。私が手作業で行うと機能しますが、SWIGが走るたびにそれをやらなければなりません。他の列挙も同様です。それに合わせてインタフェースファイルを変更することはできますか?

答えて

0

このエラーは表示されません。私はコンパイルして、次のように例をリンク:

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 

それはその後、フレキソが提案どおりに動作します。生成されたtest.pyと_test.soは同じディレクトリにあります。 DebianではPython 2.7.6とSWIG 3.0.7を使用しています。

私はVS2013とSWIG 3.0.8を使って同じことを試みました。何が起こるのは、typemap(constcode)が、静的な辞書を単に公開するconstコードを挿入するのではなく、woof_swigconstantなどの関数を生成するということです。あなたは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を使用して、私はすぐにSWIG_InstallConstants(d,swig_const_table);後に挿入、次の

{ 
    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 3.0.7から3.0.8に変わったと信じています。

+0

あなたの答えをありがとう。私はそれを価値あるものとしてVS2012でコンパイルしていますが、私は何か別のことをやっていません。問題は、生成された.pyファイルで、操作の順序がAttributeErrorになることです。コードでaroungをプレイした後、上で述べたように操作の順序を変えることで問題が解決されることがわかりましたが、生成されたpyファイルを編集しなければならないのはかなり生産的です。私はpython 3.5とSWIG 3.0.7で問題があれば作業しています。 –

+0

私はPython 2.7とSWIG 3.0.7を使い、 'foo = _test.foo'の前に' TestName = _test.TestName'を出します。私は '_test.bar_swigconstant(_test)'エントリを取得しません。それは私のために完璧に動作します。奇妙な。あなたはC++オプションを覚えていましたか? –

+0

VS2013とSWIG 3.0.8を使って仕事場で試してみましたが、動作していません。生成されたC++と.pyファイルを比較します。エラーは、生成されたC++コードにあります。 –

関連する問題