这个问题在某种程度上是这里发布的问题的扩展: SWIG_SHARED_PTR macro with templated class 尽管这个问题可能完全无关。
基本设置是这样的:我试图让 SWIG 将模板化类包装为 shared_ptr。所以接口文件应该是这样的
%shared_ptr(template_instance)
%include template_class.cpp
%template(vector_instance) template_class<int>;
Run Code Online (Sandbox Code Playgroud)
现在的问题是,template_class有很多派生类,这导致swig中出现很多警告,然后构建错误。这些类不需要作为shared_ptr's处理,所以我宁愿忽略上面代码生成的警告。错误的解决方法似乎是:
%shared_ptr(template_derived1)
%shared_ptr(template_derived2)
.
.
.
%shared_ptr(template_derivedn)
%shared_ptr(template_instance)
%include template_class.cpp
%template(vector_instance) template_class<int>;
Run Code Online (Sandbox Code Playgroud)
这是有效的,但是是一团糟,我认为将所有内容都表示为 shared_ptr 肯定有一些缺点(它是什么?)。这附近有人吗?
编辑:使用特定示例更新
测试.h
class Base
{
int base_member;
};
class Derived : public Base
{
int derived_member;
};
Run Code Online (Sandbox Code Playgroud)
测试文件
%module test
%{
#include "test.h"
#include <boost/shared_ptr.hpp>
%}
%include <boost_shared_ptr.i>
%shared_ptr(Base)
%include test.h
Run Code Online (Sandbox Code Playgroud)
命令:
swig -python -c++ test.i
g++ -fPIC -I /usr/include/python2.7 -c test_wrap.cxx
Run Code Online (Sandbox Code Playgroud)
在这个精简的示例中,swig 调用给出警告,而 g++ 调用给出错误。请注意,我已经删除了模板,因为它似乎不是问题的一个组成部分。
错误通过注释解决
%shared_ptr(Base)
Run Code Online (Sandbox Code Playgroud)
swig 产生的警告是:
test.h:10: Warning 520: Derived class 'Derived' of 'Base' is not similarly marked as a smart pointer
Run Code Online (Sandbox Code Playgroud)
来自 g++ 的错误是:
test_wrap.cxx: In function ‘PyObject* _wrap_delete_Derived(PyObject*, PyObject*)’:
test_wrap.cxx:3155:22: error: ‘smartarg1’ was not declared in this scope
Run Code Online (Sandbox Code Playgroud)
这里的警告是因为您需要告诉 SWIG 整个类层次结构,而不仅仅是基类,以便能够有效地使用智能指针。它需要能够在智能指针之间进行转换,以便任何需要智能指针 to 的东西Base也可以接受一个 to Derived。所以你的接口文件需要是:
%module test
%{
#include "test.h"
#include <boost/shared_ptr.hpp>
%}
%include <boost_shared_ptr.i>
%shared_ptr(Base)
%shared_ptr(Derived)
%include "test.h"
Run Code Online (Sandbox Code Playgroud)
它解决了警告的问题并生成了在我的机器上编译良好的代码。
如果您不想将所有派生类型告诉 SWIG,最简单的方法是对 SWIG 完全隐藏该类型 - 仅从Base您想要包装的事物中公开该类型。您可以通过几种方式做到这一点,最不干扰的是将接口文件更改为:
%module test
%{
#include "test.h"
#include <boost/shared_ptr.hpp>
%}
%include <boost_shared_ptr.i>
%ignore Derived;
%shared_ptr(Base)
%include "test.h"
Run Code Online (Sandbox Code Playgroud)
这只会导致Base被包装,因此无法再生成无法编译的代码。
或者,由于仍然需要%ignore每个类型,您可以修改头文件以完全隐藏Derived来自 SWIG的声明/定义:
class Base
{
int base_member;
};
#ifndef SWIG
class Derived : public Base
{
int derived_member;
};
#endif
Run Code Online (Sandbox Code Playgroud)
如果您的项目的组织方式使得每种类型(大致)有一个头文件,您可以通过简单地不使用%include除基本文件以外的文件来以更简单的方式执行此操作。
如果你仍然想包装它们,但不是作为 smart_ptr 我认为你将不得不接受会有很多%smart_ptr- 你可以自动生成它们吗?您也许可以使用模块来玩游戏,但我认为这并不容易,也不值得付出努力。