javaout 类型映射不适用于 std::vector 个指针

javaout typemap doesn't work for std::vector of pointers

使用 vector 个结构一切正常

%include <std_vector.i>

%typemap(javaout) const S1& std::vector<S1>::get {
  //custom code
}

struct S1 {};
std::vector<S1> val;

%template(vector_s1) std::vector<S1>;

但不适用于 vector 个指针

%include <std_vector.i>

%typemap(javaout) const S1*& std::vector<S1*>::get {
  //custom code
}

struct S1 {};
std::vector<S1*> val;

%template(vector_s1) std::vector<S1*>;

示例是使用 swig -java -c++ -module sample sample.i

编译的

SWIG 版本:

$ swig -version

SWIG Version 3.0.7

Compiled with i586-mingw32msvc-g++ [i586-pc-mingw32msvc]

Configured options: +pcre

而不是使用原始指针,为什么不使用std::shared_ptr?

此代码应按您预期的方式工作,您的 "custom code" 替换了 vector_s1.java 中的 get 函数块。

%module sample

%include <std_vector.i>
%include <std_shared_ptr.i>

%{
#include <memory>
%}

%typemap(javaout)  const std::shared_ptr<S1>& std::vector<std::shared_ptr<S1> >::get {
  //custom code
}

struct S1 {};

%shared_ptr(s1);
%template(vector_s1) std::vector<std::shared_ptr<S1> >;

如果您查看为 std::vector 提供语言独立包装代码的文件 swig/Lib/std/std_vector.i,您会发现以下注释:

// ***
// This specialization should disappear or get simplified when
// a 'const SWIGTYPE*&' can be defined
// ***
template<class _Tp, class _Alloc >
class vector<_Tp*, _Alloc > { ...

看来 SWIG 目前无法处理上面类型映射定义中的 const S1*&

现在,为 std::vector 提供 java 包装器的文件 swig/Lib/java/std_vector.i 不那么复杂并且缺少 std::vector<T*> 的专业化。

自己添加这样的专业应该可以解决您的问题:

文件std_vector_pointer.i:

%include <std_vector.i>
namespace std {
template<class T> class vector<T*> {
  public:
    typedef size_t size_type;
    typedef T* value_type;
    typedef value_type const_reference;
    vector();
    vector(size_type n);
    size_type size() const;
    size_type capacity() const;
    void reserve(size_type n);
    %rename(isEmpty) empty;
    bool empty() const;
    void clear();
    %rename(add) push_back;
    void push_back(T* x);
    %extend {
        T* get(int i) throw (std::out_of_range) {
            int size = int(self->size());
            if (i>=0 && i<size)
                return (*self)[i];
            else
                throw std::out_of_range("vector index out of range");
        }
        void set(int i, T* val) throw (std::out_of_range) {
            int size = int(self->size());
            if (i>=0 && i<size)
                (*self)[i] = val;
            else
                throw std::out_of_range("vector index out of range");
        }
    }
};
}

那么以下内容应该适用于您的上述示例:

%include "std_vector_pointer.i"

%typemap(javaout) S1* std::vector<S1*>::get {
  //custom code
}

struct S1 {};
std::vector<S1*> val;

%template(vector_s1) std::vector<S1*>;