SWIG 将 C++ 扩展到 Python,未定义的枚举
Posted
技术标签:
【中文标题】SWIG 将 C++ 扩展到 Python,未定义的枚举【英文标题】:SWIG to extend C++ to Python, undefined enum 【发布时间】:2020-03-26 16:37:12 【问题描述】:我在通过 SWIG 将 C++ 中的枚举扩展/公开到 Python 时遇到问题。
我最初创建了一个没有枚举的类“MyClass”的较小版本,并且可以正常工作,见下文:
SWIG 接口文件 (MyClassMini.i):
%module MyClassMini
%
#include "MyClassMini.h"
#include <stdio.h>
#include
#include
using namespace std;
%
%include "std_string.i"
%include "MyClassMini.h"
发出自动生成 SWIG 包装器、编译和链接的命令:
swig -python -c++ MyClassMini.i
编译和链接:
python setup.py build_ext --inplace
将新模块中的模块加载到 Python 中,实例化并设置字符串:
输出:
>Python
Type "help", "copyright", "credits" or "license" for more information.
>>> import _MyClassMini
>>> MyClassMini = _MyClassMini.new_MyClassMini();
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Wrong number or type of arguments for overloaded function 'new_MyClassMini'.
Possible C/C++ prototypes are:
MyClassMini::MyClassMini(int)
MyClassMini::MyClassMini(int,int)
MyClassMini::MyClassMini(int,int,int)
MyClassMini::MyClassMini(int,int,int,int)
>>> MyClassMini = _MyClassMini.new_MyClassMini(7);
>>> _MyClassMini.delete_MyClassMini(MyClassMini);
>>> MyClassMini = _MyClassMini.new_MyClassMini(7);
>>> _MyClassMini.MyClassMini_getType(MyClassMini);
7
>>> _MyClassMini.MyClassMini_getType(MyClassMini);
7
>>> _MyClassMini.MyClassMini_setValueString(MyClassMini,"Im a string");
>>> _MyClassMini.MyClassMini_getValueString(MyClassMini);
'Im a string'
>>> _MyClassMini.delete_MyClassMini(MyClassMini);
一切正常。
枚举问题....
我在真正的成熟课程“MyClass”上重复了相同的 SWIG 配方,唯一遇到的问题是枚举:
#1 尝试:
MyClass.i:
%module MyClass
%
#include "MyClass.h"
#include <stdio.h>
#include <iostream>
#include <cstdlib>
#include "SparseDataType.h"
using namespace std;
%
%include "std_string.i"
%include "MyClass.h"
%include "SparseDataType.h"
SWIG 接口文件SparseDataType.i:
%module SparseDataType
%
enum SparseDataType
SparseBool,
SparseChar,
SparseByte, // unsigned char
SparseInt,
SparseShort,
SparseFloat,
SparseDouble,
SparseString,
SparseComposite
;
%
MyClass.h 的一些 sn-p:
#ifndef MyClass_H
#define MyClass_H
#include <stdio.h>
#include <iostream>
#include <string.h>
#include "SparseDataType.h"
using namespace std;
class MyClass
public:
/*constructors:*/
/*if type is scaler, assume size 1
n is size (if type is scalar, ignore size)*/
MyClass (SparseDataType SparseDataType)
size = _n3 = _n2 = _n1= 1;
_type = SparseDataType;
alloc();
MyClass (SparseDataType SparseDataType, int size_n1)
size = _n1= size_n1;
_n2 = _n3 = 1;
_type = SparseDataType;
alloc();
// 2d array
MyClass (SparseDataType SparseDataType, int size_n2 , int size_n1)
_n1 = size_n1;
_n2 = size_n2;
_n3 = 1;
size = _n2 * _n1;
_type = SparseDataType;
alloc();
// 3d array
MyClass (SparseDataType SparseDataType, int size_n3 , int size_n2, int size_n1)
_n3 = size_n3;
_n2 = size_n2;
_n1 = size_n1;
size = _n3 * _n2 * _n1;
_type = SparseDataType;
alloc();
//etc…
I edited setup.py to include SparseDataType:
from distutils.core import setup, Extension
MyClass_module = Extension('_MyClass',
sources=['MyClass_wrap.cxx'],
)
SparseDataType_module = Extension('_SparseDataType',
sources=['SparseDataType_wrap.cxx'],
)
setup (name = 'MyClass',
version = '0.1',
author = "SWIG Docs",
description = """Simple swig MyClass from docs""",
ext_modules = [MyClass_module,SparseDataType_module],
py_modules = ["MyClass"],
)
**Then I ran SWIG wrapper auto-generation commands again & compilation & linking again:**
swig -python -c++ MyClass.i
swig -python -c++ SparseDataType.i
python setup.py build_ext –inplace
目前没有错误,全部编译。 导入python没问题,但实例化有问题(枚举类型未解析):
devlinuxuser1% python
Python 2.7.5 (default, Aug 2 2016, 04:20:16)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import _MyClass
>>> import _SparseDataType
>>> MyClass = _MyClass.new_MyClass(_SparseDataType.SparseInt);
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'SparseInt'
第 2 次尝试已更改,%module SparseDataType.i(基于 Wrapping C-enum in a Python module with Swig):
%module SparseDataType
%inline %
struct mySparseDataType
enum
SparseBool,
SparseChar,
SparseByte, // unsigned char
SparseInt,
SparseShort,
SparseFloat,
SparseDouble,
SparseString,
SparseComposite
;
;
%
然后我重新运行 SWIG 命令:
swig -python -c++ MyClass.i
swig -python -c++ SparseDataType.i
python setup.py build_ext –inplace
目前没有错误,全部编译完毕。
devlinuxuser1% python
>>> import _MyClass
>>> import _SparseDataType
>>> MyClass = _MyClass.new_MyClass(_SparseDataType.mySparseDataType.SparseInt);
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'mySparseDataType'
>>> MyClass = _MyClass.new_MyClass(_SparseDataType.SparseInt); Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'SparseInt'
>>> MyClass = _MyClass.new_MyClass(mySparseDataType.SparseInt); Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'mySparseDataType' is not defined
再次无法解析枚举“未定义”??
关于如何从 Python 调用枚举的任何想法?
谢谢一百万!
【问题讨论】:
【参考方案1】:import SparseDataType
不是import _SparseDataType
。后者直接导入_SparseDataType.pyd
并绕过打算导入的SparseDataType.py
包装器。
然后,SparseDataType.mySparseDataType.SparseInt
将访问枚举值。 enum
位于结构内部,因此您需要 module.structure.enum
才能访问它。
【讨论】:
以上是关于SWIG 将 C++ 扩展到 Python,未定义的枚举的主要内容,如果未能解决你的问题,请参考以下文章
从 c++ 到 python 的 SWIG:未定义的符号导入问题 [关闭]
使用 SWIG 为 Python 包装 C++。 “向量”未声明
ImportError:使用 SWIG 时 _...so 文件中的未定义符号