2012-05-15 23 views
6

tôi cố gắng để tạo ra mã java với SWIGstd :: vector để sinh mã java.util.Vector với uống một lân

Trong MyList.h tôi tuyên bố một đối tượng danh sách tùy chỉnh được gọi _list

List<T*> _list; 

và Danh mục này lớp kế thừa từ vector

class List : public vector<T> 

trong một lớp học kinh doanh (trong C++) tôi trả về một Li st tùy chỉnh các đối tượng

List<MyObject> getMyList(){ 
    .... 
    return list; 
} 

vì vậy tôi muốn tạo ra mã java nơi tôi có thể lấy này C++ Danh sách như java.util.List hoặc java.util.Vector.

trong tập tin swig.i của tôi, tôi không thể xoay sở như thế nào để thể hiện

%typemap(jstype) List "java.util.Vector" 
namespace std { 
    %template(CustomVector) vector<MyObject>; 
} 

bất kỳ loại giúp đỡ làm thế nào để cấu hình mẫu này tập tin swig.i hoặc một số mẫu mã để tạo ra một java.util.List/Chức năng trả về Vector sẽ được đánh giá cao.

Cảm ơn bạn.

+0

Hãy có một cái nhìn tại http: // stackoverflow.com/câu hỏi/1854335/how-to-tạo-một-java-đẳng cấp tương tự-to-ac-template-class và http://stackoverflow.com/questions/462297/how- sử dụng-classt-in-java – phantasmagoria

+2

Liên quan đến thừa kế 'std :: vector', hãy xem [câu hỏi này] (http://stackoverflow.com/questions/4353203/thou-shalt-not-inherit-từ -stdvector). – juanchopanza

+0

OK giả sử tôi sẽ không sử dụng/trả về một std :: vector sau đó làm thế nào tôi có thể chuyển danh sách các đối tượng từ lớp C++ sang lớp java của tôi. –

Trả lời

10

Bạn không thực sự muốn chạm vào java.util.Vector với giao diện được bao bọc bởi vì bạn sẽ kết thúc sao lưu bộ nhớ hoặc thực hiện số lượng lớn thao tác sao chép mỗi khi bạn chuyển nó vào/ra khỏi một hàm. (Cũng lưu ý rằng nói chung trong C++ từ container là thiết kế lẻ).

Thay vào đó trong Java, điều "đúng" cần làm là kế thừa từ java.util.AbstractList. Câu trả lời này là một phiên bản chung của tôi older answer to a similar question.

Nó hoạt động cho tất cả các loại std::vector, không chỉ là loại cố định và xử lý primitives which need to be accessed via Objects bằng bản đồ kiểu tùy chỉnh "hộp số tự động". Thiếu hỗ trợ dành cho chuyên ngành std::vector<bool>, nhưng điều đó sẽ đơn giản để thêm nếu bạn cần.

%{ 
#include <vector> 
#include <stdexcept> 
%} 

%include <stdint.i> 
%include <std_except.i> 

namespace std { 

    template<class T> class vector { 
     public: 
     typedef size_t size_type; 
     typedef T value_type; 
     typedef const value_type& const_reference; 
     vector(); 
     vector(size_type n); 
     vector(const vector& o); 
     size_type capacity() const; 
     void reserve(size_type n); 
     %rename(isEmpty) empty; 
     bool empty() const; 
     void clear(); 
     void push_back(const value_type& x); 
     %extend { 
      const_reference get(int i) const throw (std::out_of_range) { 
       return $self->at(i); 
      } 
      value_type set(int i, const value_type& VECTOR_VALUE_IN) throw (std::out_of_range) { 
       const T old = $self->at(i); 
       $self->at(i) = VECTOR_VALUE_IN; 
       return old; 
      } 
      int32_t size() const { 
       return $self->size(); 
      } 
      void removeRange(int32_t from, int32_t to) { 
       $self->erase($self->begin()+from, $self->begin()+to); 
      } 
     } 
    }; 
} 

// Java typemaps for autoboxing in return types of generics 
%define AUTOBOX(CTYPE, JTYPE) 
%typemap(autobox) CTYPE, const CTYPE&, CTYPE& "JTYPE" 
%enddef 
AUTOBOX(double, Double) 
AUTOBOX(float, Float) 
AUTOBOX(boolean, Boolean) 
AUTOBOX(signed char, Byte) 
AUTOBOX(short, Short) 
AUTOBOX(int, Integer) 
AUTOBOX(long, Long) 
AUTOBOX(SWIGTYPE, $typemap(jstype,$1_basetype)) 

%typemap(javabase) std::vector "java.util.AbstractList<$typemap(autobox,$1_basetype::value_type)>" 
%typemap(javainterface) std::vector "java.util.RandomAccess" 
%typemap(jstype) std::vector get "$typemap(autobox,$1_basetype)" 
%typemap(jstype) std::vector set "$typemap(autobox,$1_basetype)" 
%typemap(jstype) std::vector &VECTOR_VALUE_IN "$typemap(autobox,$1_basetype)" 
%typemap(javacode) std::vector %{ 
    $javaclassname(java.util.Collection<$typemap(autobox,$1_basetype::value_type)> e) { 
    this.reserve(e.size()); 
    for($typemap(autobox,$1_basetype::value_type) value: e) { 
     this.push_back(value); 
    } 
    } 
%} 

Hầu hết trong số này là khá giống với std_vector.i mặc định mà SWIG hiện đang cung cấp, các bit mới là việc đổi tên, mở rộng và typemaps rằng mở rộng AbstractList và thực hiện RandomAccess. Nó cũng bổ sung thêm một hàm tạo khác với các tên khác là Collection s - đây là tài liệu Java được khuyến nghị và dễ thực hiện. (Có quá tải cho các loại khác std::vectornhiều hơn nhanh hơn).

Tôi đã thử nghiệm gói vector này trong vòng một giao diện SWIG:

%module test 

%include "vector.i" 

%template(DblVec) std::vector<double>; 
%template(ByteVec) std::vector<signed char>; 
%include <std_string.i> 
%template(StringVec) std::vector<std::string>; 

%inline %{ 
struct foo {}; 
%} 

%template(FooVec) std::vector<foo>; 

Mà tôi đã có thể biên dịch và chạy với:

public class run { 
    public static void main(String argv[]) { 
    System.loadLibrary("test"); 
    DblVec dv = new DblVec(100); 
    for (int i = 0; i < 100; ++i) { 
     dv.set(i,(double)i); 
    } 
    FooVec fv = new FooVec(1); 
    fv.set(0, new foo()); 
    for (double d: dv) { 
     System.out.println(d); 
    } 
    } 
} 
+0

(Thử nghiệm với SWIG 2.0.4) – Flexo

+0

Xin chào. Bạn vẫn khuyên bạn nên sử dụng trình bao bọc này thay vì thực hiện 'std_vector.i' của SWIG? Tôi chỉ cần trao đổi dữ liệu mảng nguyên thủy trong trường hợp của tôi. Cảm ơn! –

+0

@ JesúsZazueta nếu nó chỉ là một loạt các nguyên thủy tôi có lẽ chỉ cần sử dụng giao diện mảng JNI để làm điều đó và lấy hit trên một hoặc hai bản sao. (Hoặc tái làm việc mã để nó có thể sử dụng một bộ đệm mượn từ Java và chia sẻ cùng một bộ nhớ). – Flexo

Các vấn đề liên quan