SWIG - 当方法具有枚举类型参数时出现 OverflowError
SWIG - OverflowError when methods have enum typed arguments
我有一个 C++ 代码库,它使用 SWIG 生成 Python 3 个接口。
我有一个 无法将 enum
值转换为足够大的类型。在很好的帮助下解决了这个问题。
现在我有一个与另一个问题相关的新问题。当最大的 enum
值作为参数传入时,将更正后的 enum
值作为参数的方法将抛出 OverflowError
。
我想知道是否有使用 typemap
函数解决此问题的通用方法(就像枚举对象的方法)。识别所有将 enum
常量作为参数的方法。或者我是否需要为每个 enum
类型定义一个 in
typemap
?
我已经尝试过并且有效的方法是将其包含在 .i
文件中:
%include "typemaps.i"
%apply unsigned long long { doom::Bar::FooPresence };
但如果有一种“包罗万象”的东西就好了,比如 constcode
类型映射。
重现当前行为所需的代码:
bar.h
namespace doom
{
class Bar
{
public:
struct FooIdent
{
enum Ident
{
UnknownFoo = 0,
KnownFoo = 1,
MainFoo = 2,
SecondaryFoo = 3
};
};
enum FooPresence
{
Boo = 0x0,
Foo1 = 0x8000000000ULL,
Foo2 = 0x4000000000ULL,
Foo3 = 0x2000000000ULL,
FooWithA1 = 0x1000000000ULL,
FooWithA2 = 0x0800000000ULL,
FooWithA3 = 0x0400000000ULL,
FooWithA4 = 0x0200000000ULL,
FooWithB1 = 0x0100000000ULL,
FooWithB2 = 0x0080000000,
FooWithB3 = 0x0040000000
};
Bar();
void setVesODee( int ves, doom::Bar::FooPresence pr );
void setVesOGoo( int goo, doom::Bar::FooIdent::Ident ide );
int doSomething();
private:
int m_vdee;
int m_vgoo;
};
} // namespace doom
bar.cpp
#include "bar.h"
#include <iostream>
namespace doom
{
Bar::Bar()
{
m_vdee = 0;
m_vgoo = 0;
}
void Bar::setVesODee( int ves, doom::Bar::FooPresence pr ) {
m_vdee = static_cast< doom::Bar::FooPresence >( ves & pr );
}
void Bar::setVesOGoo( int goo, doom::Bar::FooIdent::Ident ide ) {
m_vgoo = static_cast< doom::Bar::FooIdent::Ident >( goo & ide );
}
int Bar::doSomething() {
return m_vgoo + m_vdee;
}
} // namespace doom
int main() {
doom::Bar b = doom::Bar();
b.setVesODee(3, doom::Bar::FooWithB2);
b.setVesOGoo(4, doom::Bar::FooIdent::MainFoo);
int c = b.doSomething();
std::cout << c << std::endl;
return 0;
}
bar.i
%module bar
%feature ("flatnested");
%{
#define SWIG
#include "bar.h"
#define SWIG_PYTHON_STRICT_BYTE_CHAR
%}
%typemap(constcode) int %{
SWIG_Python_SetConstant(d, "$symname", PyLong_FromLongLong(static_cast<long long>()));
%}
%rename("Bar_%s", %$isnested) "";
%include "bar.h"
test_bar.py
import bar
b = bar.Bar()
b.setVesODee(10, bar.Bar.Foo1)
build-and-test.sh
#!/bin/bash
set -e
echo "Cleanup..."
rm -rf __pycache__
rm -f _bar.so bar.o bar_wrap.*
echo "Building..."
swig -python -c++ -py3 -debug-tmsearch bar.i
g++ -fPIC -c $(pkg-config --cflags --libs python3) bar.cpp bar_wrap.cxx
g++ -shared -o _bar.so bar.o bar_wrap.o
echo "Testing..."
python3 test_bar.py
output
Traceback (most recent call last):
File "test_bar.py", line 15, in <module>
b.setVesODee(10, bar.Bar.Foo1)
File "/workspace/ctmp/bar.py", line 83, in setVesODee
return _bar.Bar_setVesODee(self, ves, pr)
OverflowError: in method 'Bar_setVesODee', argument 3 of type 'doom::Bar::FooPresence'
SWIGTYPE
是未找到 type-specific 匹配时的默认类型匹配。您可以使用以下内容应用于所有枚举:
%apply unsigned long long { enum SWIGTYPE };
参见 13.3.3 Default typemap matching rules in the SWIG documentation。
示例:
test.i
%module test
%typemap(constcode) int %{SWIG_Python_SetConstant(d, "",PyLong_FromLongLong(static_cast<long long>()));%}
%apply unsigned long long { enum SWIGTYPE };
%{
#include <iostream>
%}
%inline %{
enum FooPresence : unsigned long long
{
Foo1 = 0x8000000000ULL,
};
void func(FooPresence x) {
std::cout << std::hex << static_cast<unsigned long long>(x) << std::dec << std::endl;
}
%}
演示:
>>> import test
>>> test.func(test.Foo1)
8000000000
我有一个 C++ 代码库,它使用 SWIG 生成 Python 3 个接口。
我有一个 enum
值转换为足够大的类型。在很好的帮助下解决了这个问题。
现在我有一个与另一个问题相关的新问题。当最大的 enum
值作为参数传入时,将更正后的 enum
值作为参数的方法将抛出 OverflowError
。
我想知道是否有使用 typemap
函数解决此问题的通用方法(就像枚举对象的方法)。识别所有将 enum
常量作为参数的方法。或者我是否需要为每个 enum
类型定义一个 in
typemap
?
我已经尝试过并且有效的方法是将其包含在 .i
文件中:
%include "typemaps.i"
%apply unsigned long long { doom::Bar::FooPresence };
但如果有一种“包罗万象”的东西就好了,比如 constcode
类型映射。
重现当前行为所需的代码:
bar.h
namespace doom
{
class Bar
{
public:
struct FooIdent
{
enum Ident
{
UnknownFoo = 0,
KnownFoo = 1,
MainFoo = 2,
SecondaryFoo = 3
};
};
enum FooPresence
{
Boo = 0x0,
Foo1 = 0x8000000000ULL,
Foo2 = 0x4000000000ULL,
Foo3 = 0x2000000000ULL,
FooWithA1 = 0x1000000000ULL,
FooWithA2 = 0x0800000000ULL,
FooWithA3 = 0x0400000000ULL,
FooWithA4 = 0x0200000000ULL,
FooWithB1 = 0x0100000000ULL,
FooWithB2 = 0x0080000000,
FooWithB3 = 0x0040000000
};
Bar();
void setVesODee( int ves, doom::Bar::FooPresence pr );
void setVesOGoo( int goo, doom::Bar::FooIdent::Ident ide );
int doSomething();
private:
int m_vdee;
int m_vgoo;
};
} // namespace doom
bar.cpp
#include "bar.h"
#include <iostream>
namespace doom
{
Bar::Bar()
{
m_vdee = 0;
m_vgoo = 0;
}
void Bar::setVesODee( int ves, doom::Bar::FooPresence pr ) {
m_vdee = static_cast< doom::Bar::FooPresence >( ves & pr );
}
void Bar::setVesOGoo( int goo, doom::Bar::FooIdent::Ident ide ) {
m_vgoo = static_cast< doom::Bar::FooIdent::Ident >( goo & ide );
}
int Bar::doSomething() {
return m_vgoo + m_vdee;
}
} // namespace doom
int main() {
doom::Bar b = doom::Bar();
b.setVesODee(3, doom::Bar::FooWithB2);
b.setVesOGoo(4, doom::Bar::FooIdent::MainFoo);
int c = b.doSomething();
std::cout << c << std::endl;
return 0;
}
bar.i
%module bar
%feature ("flatnested");
%{
#define SWIG
#include "bar.h"
#define SWIG_PYTHON_STRICT_BYTE_CHAR
%}
%typemap(constcode) int %{
SWIG_Python_SetConstant(d, "$symname", PyLong_FromLongLong(static_cast<long long>()));
%}
%rename("Bar_%s", %$isnested) "";
%include "bar.h"
test_bar.py
import bar
b = bar.Bar()
b.setVesODee(10, bar.Bar.Foo1)
build-and-test.sh
#!/bin/bash
set -e
echo "Cleanup..."
rm -rf __pycache__
rm -f _bar.so bar.o bar_wrap.*
echo "Building..."
swig -python -c++ -py3 -debug-tmsearch bar.i
g++ -fPIC -c $(pkg-config --cflags --libs python3) bar.cpp bar_wrap.cxx
g++ -shared -o _bar.so bar.o bar_wrap.o
echo "Testing..."
python3 test_bar.py
output
Traceback (most recent call last):
File "test_bar.py", line 15, in <module>
b.setVesODee(10, bar.Bar.Foo1)
File "/workspace/ctmp/bar.py", line 83, in setVesODee
return _bar.Bar_setVesODee(self, ves, pr)
OverflowError: in method 'Bar_setVesODee', argument 3 of type 'doom::Bar::FooPresence'
SWIGTYPE
是未找到 type-specific 匹配时的默认类型匹配。您可以使用以下内容应用于所有枚举:
%apply unsigned long long { enum SWIGTYPE };
参见 13.3.3 Default typemap matching rules in the SWIG documentation。
示例:
test.i
%module test
%typemap(constcode) int %{SWIG_Python_SetConstant(d, "",PyLong_FromLongLong(static_cast<long long>()));%}
%apply unsigned long long { enum SWIGTYPE };
%{
#include <iostream>
%}
%inline %{
enum FooPresence : unsigned long long
{
Foo1 = 0x8000000000ULL,
};
void func(FooPresence x) {
std::cout << std::hex << static_cast<unsigned long long>(x) << std::dec << std::endl;
}
%}
演示:
>>> import test
>>> test.func(test.Foo1)
8000000000