使用swig的auto_ptr

2 投票
2 回答
890 浏览
提问于 2025-04-16 05:19

我正在尝试将一个使用了auto_ptr的C++库进行封装。我使用的是swig,想要生成Python的绑定代码。我看过swig文档中关于如何使用智能指针的部分,具体可以在这里找到。但是我一直没能成功。

Swig生成的代码试图用一个常量引用来初始化auto_ptr,但auto_ptr的复制构造函数是用一个非常量引用定义的,比如说auto_ptr(auto_ptr &)。生成的代码在编译时出现了“丢弃常量限定符”的错误。当我手动删除常量限定符后,代码就能正常编译了。

我在很多邮件列表中找过相关信息,但都没有帮助。有没有人能给我一个可以正常工作的例子?我的不工作示例在这里:

%module auto_ptr_test
%{
#include <memory>
#include <iostream>
using namespace std;
%}
namespace std {
template <class T>
class auto_ptr {
    auto_ptr();
    auto_ptr(auto_ptr &);
    T *operator->() const;
};
}

%inline %{
class Test {
Test() {
    cout << "Test()" << endl;
}
public:
static std::auto_ptr<Test> create() const {
    return auto_ptr<Test>(new Test());
}
void greet() {
    cout << "hello" << endl;
}
};
%}

%template () std::auto_ptr<Test>;

我使用cmake编译了它,以下是我的CMakeLists.txt:

cmake_minimum_required(VERSION 2.8)
find_package(SWIG REQUIRED)
include(${SWIG_USE_FILE})

FIND_PACKAGE(PythonLibs)
INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH})

INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})

SET(CMAKE_SWIG_FLAGS "")

SET_SOURCE_FILES_PROPERTIES(auto_ptr_test.i PROPERTIES CPLUSPLUS ON)
SWIG_ADD_MODULE(auto_ptr_test python auto_ptr_test.i)
SWIG_LINK_LIBRARIES(auto_ptr_test ${PYTHON_LIBRARIES})

2 个回答

1

我在libRETS中找到了如何实现的提示,你需要针对每个方法单独处理:

http://code.crt.realtors.org/projects/librets/browser/librets/trunk/project/swig/auto_ptr_release.i?rev=HEAD

基本上,你需要把从C++接收到的auto_ptr解包,然后在传递给C++之前再重新包装。下面是需要放入.i文件中的代码示例:

    //original prototype:
    //virtual void SetSomething(std::auto_ptr<ValueClass> value) = 0;
    //replacement to be generated by SWIG:
    %extend{
        void SetSomething(ValueClass *value){
            std::auto_ptr<ValueClass> tmp(value);
            $self->SetSomething(tmp);
        }
    }


  //retrieving object wrapped in auto_ptr using swig macro:
  %define SWIG_RELEASE_AUTO_PTR(RETURN_TYPE, METHOD_NAME, PROTO, ARGS)
    %extend {
    RETURN_TYPE * METHOD_NAME PROTO {
        std::auto_ptr<RETURN_TYPE> auto_result = self->METHOD_NAME ARGS;
        return auto_result.release();
    }
  }
  %enddef
  // and then inside class:
  // virtual auto_ptr<ValueClass> SomeMethod(const string& foo) = 0;
  // replaced with:
  SWIG_RELEASE_AUTO_PTR(ValueClass,SomeMethod,(const string& foo),(foo));
1

我觉得你可能无法顺利地把这段代码用SWIG封装起来。问题在于,auto_ptr在复制的时候会改变所有权。这就是为什么它的复制构造函数不能加const的原因。SWIG内部管理对象所有权的方式意味着,如果没有很多自定义的SWIG代码,你很难实现想要的所有权行为。

撰写回答