I'm trying to wrap a C++ library which uses auto_ptr. I'm using swig and want to generate python bindings. I'v seen the section of the swig docu on how to use swig with smart pointers here. But I can't get it to work.
Swig generates code that wants to initialize the auto_ptr using a const reference, but auto_ptr defines the copy constructor with a non-const reference e.g. auto_ptr(auto_ptr &). The generated code does not compile with "discards const qualifiers". When I manually delete the const qualifier the code compiles fine.
I'v seen lots of mailing list entries but nothing helped. Can someone provide me with a working example. My non working sample is here:
%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>;
I compiled it using cmake with the following 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})
I do not believe you are going to be able to successfully wrap this code in SWIG. The problem is that auto_ptr changes ownership when it copies. This is why it requires the copy constructor to not have const. The way that SWIG manages ownership of objects internally means that the it is unlikely you'll get the desired ownership behavior without a lot of custom SWIG code.
I found hint how to do it in libRETS, and you need to do it on per-method basis:
Basically you want to unwrap auto_ptr you receive from C++ and wrap it before passing to C++. Example of code to be put into .i file is:
//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));
来源:https://stackoverflow.com/questions/3906019/auto-ptr-with-swig