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::vector
là nhiề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);
}
}
}
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
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
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. –