分解SWIG Python接口 - 容器会产生命名空间冲突
Breaking up SWIG Python interface -- containers create namespace conflict
我们的代码库目前支持单个SWIG接口文件(用于Python(,该文件多年来已经发展到包括大约300个C++类(技术接口(,所有这些类都继承自单个基类,并且都存在于单个全局命名空间中。 这使我们能够使用最少量的 SWIG 代码在 SWIG 类表示的C++类之间实现动态转换,同时通过将C++继承结构排除在 SWIG 之外来简化。
只要我们在单个模块中编译我们的 SWIG 接口,这种机制就可以很好地工作——但随着 SWIG 接口文件的增长,它变得难以管理,编译/链接时间也增加了。 为了解决这个问题,我按派生类的名称将接口文件拆分为单独的模块——一个模块用于以"A"到"G"开头的类名,一个用于以"H"到"N"开头的名称,等等,从而产生了四个派生类模块和一个基类模块。 我能够按照此处概述的方法编译和链接这些模块,并展示动态强制转换的预期行为:(http://www.swig.org/Doc3.0/SWIGDocumentation.html#Modules_nn1(
但是,当容器发挥作用时,将单个模块分成四个部分(计算基类的五个部分(会导致命名空间出现问题。 考虑以下函数,来自我的 v-to-z 接口文件中的类:
void RemoveIsolated(const std::vector<global::IFoo*> spRemoveIsolated) {
。 }
这需要全局命名空间中存在的派生类之一的向量。 当我只有一个模块时,这没有问题,但现在类 IFoo 存在于 a-to-g 模块中——所以如果我将某些内容转换为 IFoo*,那就是 a-to-g。呜*。 但是,该函数需要一个全局::IFoo*。
这种情况似乎可以通过SWIG模板机制来解决。 我见过这样的讨论,其中人们通过一次(可能在基类的接口文件中??(声明
%template(FooVector) std::vector<global::Foo*>;
在另一点(可能在派生类的接口文件中??
%template () std::vector<global::Foo*>;
但我实施这一点的尝试并没有成功。 讨论有些模棱两可,可能是我做错了什么。 任何人都可以提供澄清,最好是举例说明吗?
看起来你缺少的信息是%import
指令,它允许模块与类型的定义合作,而无需重复它们,并且仍然以单个包装类型结束。文档建议使用它来减小模块大小。
可能您需要做的就是将您的 v 到 z 模块%import
a 到 g 模块,以使其为您工作。(就个人而言,我会尝试按功能而不是按字母顺序划分它们,因此两者之间的依赖关系不会成为问题(
感谢您的建议柔版印刷。 导入 a-to-g 模块不起作用;C++编译器抱怨说,当它尝试编译为 V-to-Z 包装器文件时,声明的所有类(接口(都不是全局命名空间的一部分。 然而,通过练习,我质疑为什么我们以前在编译单个模块时取得了成功。 事实证明,我们在接口文件中为单个模块使用了一个类型映射宏,该模块将采用
const std::vector<global::IFoo*>
并这样映射它:
TYPEMAPMACRO(global::IFoo, SWIGTYPE_p_global__IFoo)
对于矢量容器。 对于任何感兴趣的人来说,宏本身是:
%define TYPEMAPMACRO(type, name)
%typemap(in) const std::vector {
/*Check if is a list */
std::vector vec;
void *pobj = 0;
if(PyTuple_Check($input))
{
size_t size = PyTuple_Size($input);
for (size_t j = 0; j < size; j++) {
PyObject *o = PyTuple_GetItem($input, j);
void *argp1 = 0 ;
int res1 = SWIG_ConvertPtr(o, &argp1, name, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Typemap of std::vector" "', argument " "1"" of type '" """'");
}
vec.push_back(reinterpret_cast< type * >(argp1));
}
$1 = vec;
}
else if (SWIG_IsOK(SWIG_ConvertPtr($input, &pobj, name, 0 | 0 ))) {
PyObject *o = $input;
void *argp1 = 0 ;
int res1 = SWIG_ConvertPtr(o, &argp1, name, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Typemap of std::vector" "', argument " "1"" of type '" """'");
}
vec.push_back(reinterpret_cast< type * >(argp1));
$1 = vec;
}
else {
PyErr_SetString(PyExc_TypeError, "not a list");
return NULL;
}
}
%typecheck(SWIG_TYPECHECK_POINTER) std::vector {
void *pobj = 0;
if(!PyTuple_Check($input) && !SWIG_IsOK(SWIG_ConvertPtr($input, &pobj, name, 0 | 0 ))) {
$1 = 0;
PyErr_Clear();
} else {
$1 = 1;
}
}
%enddef
我的感觉是,这是标准的样板内容,我并不声称理解它,因为它是别人的代码,但是我现在理解的是,我以前没有理解的是,我需要将类型映射的宏放在使用类型映射的函数之前(例如上面的"RemoveIsolated"示例(。 当我把我的大模块分成小模块时,这个顺序被打破了。
- 如何使 std::sort 在 std::swap 和我的命名空间的模板化交换之间没有名称冲突?
- C++ |匿名命名空间与命名空间 std 冲突
- 分解SWIG Python接口 - 容器会产生命名空间冲突
- 如何解决两个不使用命名空间的第三方库之间的类名冲突?
- 调用 ADL 时,表达式和命名空间之间是否会发生冲突
- 类名和枚举值之间的冲突:无需命名空间即可解析
- C++当命名空间、类名和命名空间::类名冲突时该怎么办
- C++ 中的命名空间冲突
- 避免与具有相同名称的两个类发生命名空间冲突
- 命名与多个命名空间冲突
- 命名空间中的类名冲突
- ctime std::命名空间冲突
- 如何避免 C 和 C++ 中的命名空间冲突
- C++ 当命名空间发生冲突时,为什么结构/类不与变量和函数发生冲突?
- 我收到void main()和使用命名空间std;之间的冲突;?我正在使用代码块
- 全局作用域枚举和命名空间冲突
- 如何解决c++中的命名空间冲突?
- 不明确的引用和命名空间(来自两个外部库的定义冲突)
- 命名空间,类成员ADL冲突
- 在c++中命名命名空间的最佳方法//当名称冲突时该怎么做