error: Do not know conversation from Java type to such rust type 'Vec < String >'
Similar to #270, I'm not able to use Vec<String> or Vec<&str> as an input parameter.
I tried declaring something like:
mod swig_foreign_types_map {}
foreign_typemap!(
($p:r_type) Vec<String> => jobjectArray {
$out = jobject_array_to_vec_of_objects(env, $p);
};
);
but that didn't seem to work.
I think if String implemented SwigForeignClass, the default implementation would just work?
Something like this seems to work, although untested:
mod swig_foreign_types_map {}
fn jstring_array_to_vec_of_strings(env: *mut JNIEnv, arr: jobjectArray) -> Vec<String> {
let length = unsafe { (**env).GetArrayLength.unwrap()(env, arr) };
let len = <usize as ::std::convert::TryFrom<jsize>>::try_from(length)
.expect("invalid jsize, in jsize => usize conversation");
let mut result = Vec::with_capacity(len);
for i in 0..length {
let native: String = unsafe {
let obj: jstring = (**env).GetObjectArrayElement.unwrap()(env, arr, i);
if (**env).ExceptionCheck.unwrap()(env) != 0 {
panic!("Failed to retrieve element {} from this `jobjectArray'", i);
}
let jstr = JavaString::new(env, obj);
jstr.to_str().to_string()
};
result.push(native);
}
result
}
#[swig_from_foreigner_hint = "java.lang.String []"]
impl SwigFrom<jobjectArray> for Vec<String> {
fn swig_from(x: jobjectArray, env: *mut JNIEnv) -> Self {
jstring_array_to_vec_of_strings(env, x)
}
}
I think if String implemented SwigForeignClass, the default implementation would just work?
Yes, but then this code
foreign_class(class Foo {
fn f() -> String;
});
would be converted to Java code that return custom String from user's package,
not java.lang.String.
Though you can define in your code:
type VecOfStrings = Vec<String>;
foreigner_class!(class VecOfStrings {
self_type VecOfStrings;
constructor create() -> VecOfStrings {
Vec::new()
}
fn VecOfStrings::len(&self) -> usize;
fn at(&self, i: usize) -> QRustStrView {
&this[i]
}
fn push_back(&mut self, s: QString) {
this.push(s);
}
});
Code above is part of my code to use Rust from Qt/C++, but I suppose you can get the idea how it can be used in Java case.
@Dushistov Would you be willing to accept the code I provided in the followup comment here https://github.com/Dushistov/rust_swig/issues/289#issuecomment-538271349 as a pull request?
After some testing, it seems to work fine locally and it allows accepting Vec<String> as an input parameter without having to wrap it.
@archseer
Would you be willing to accept the code I provided in the followup comment
Not sure. At first java.lang.String (which uses utf-16 internally) converted by JVM to utf-8 via memory allocation, then result is not used "as is" instead we make additional n+1 allocations to convert it into Vec<String>.
It may be suitable if your API really use Vec<String> as input parameter,
but if it can accept something like Iterator<Item = &str> it can be done without additional memory allocations.
So I am not sure yet about what type mapping related to String [] to use in rust_swig and
which one is up to users of rust_swig to use in their custom type mappings via merge_type_map
So I am not sure yet about what type mapping related to String [] to use in rust_swig and which one is up to users of rust_swig to use in their custom type mappings via merge_type_map
if blow feature to be support, maybe this solution more smart (lazy memory allocation):
foreign_callback!(callback BuildList<String>{
self_type Iterator<Item = String>;
onNext = Iterator<Item = String >::next(&mut self) -> Option<Self::Item>;
});
And java part like below:
// gen by rust_swig
interface BuildList<T> {
Optional<T> onNext();
}
class BuildListImpl<T> implement BuildList<T> {
List<T> list = new LinkList();
@override
Optional<T> onNext() {
// TODO: list.getNext();
}
}
class Demo {
native consumeList(BuildList<String> list);
}
rust part:
struct Demo;
impl Demo {
consumeList(list: Box<Iterator<Item = String>>) {
list.iter().map(….) …….
}
}
foreign_class!(class Demo {
self_type Demo;
fn Demo::consumeList(list: Box<Iterator<Item = String>>);
});
It may be suitable if your API really use
Vec<String>as input parameter, but if it can accept something likeIterator<Item = &str>it can be done without additional memory allocations.So I am not sure yet about what type mapping related to
String []to use inrust_swigand which one is up to users ofrust_swigto use in their custom type mappings via merge_type_map
I've been trying to figure out but can't. How can I accept a string (or object for that matter) iterator in my Rust API?
Thanks!