Repository: dtolnay/cxx (language: rust)

Issue:
Support Vec<String> and CxxVector<CxxString>
These were omitted from the original round of vector PRs but both should be possible to support.


Discussion / hints:
Do you have any suggestions for how to go about implementing this?

Are there workarounds such as passing `&str`? (I did try this and couldn't get it working either, but I may have been doing something wrong).

Fix patch:
diff --git a/src/cxx.cc b/src/cxx.cc
index e00fd6ae6..2114598f6 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -276,7 +276,8 @@ void cxxbridge03$unique_ptr$std$string$drop(
 #define FOR_EACH_STD_VECTOR(MACRO)                                             \
   FOR_EACH_NUMERIC(MACRO)                                                      \
   MACRO(usize, size_t)                                                         \
-  MACRO(isize, rust::isize)
+  MACRO(isize, rust::isize)                                                    \
+  MACRO(string, std::string)
 
 #define FOR_EACH_RUST_VEC(MACRO)                                               \
   FOR_EACH_NUMERIC(MACRO)                                                      \
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index bfb4a4e37..10853a62d 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -1,3 +1,4 @@
+use crate::cxx_string::CxxString;
 use std::ffi::c_void;
 use std::fmt::{self, Display};
 use std::marker::PhantomData;
@@ -129,16 +130,16 @@ pub unsafe trait VectorElement: Sized {
     unsafe fn __unique_ptr_drop(repr: *mut c_void);
 }
 
-macro_rules! impl_vector_element_for_primitive {
-    ($ty:ident) => {
+macro_rules! impl_vector_element {
+    ($segment:expr, $name:expr, $ty:ty) => {
         const_assert_eq!(1, mem::align_of::<CxxVector<$ty>>());
 
         unsafe impl VectorElement for $ty {
-            const __NAME: &'static dyn Display = &stringify!($ty);
+            const __NAME: &'static dyn Display = &$name;
             fn __vector_size(v: &CxxVector<$ty>) -> usize {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$std$vector$", stringify!($ty), "$size")]
+                        #[link_name = concat!("cxxbridge03$std$vector$", $segment, "$size")]
                         fn __vector_size(_: &CxxVector<$ty>) -> usize;
                     }
                 }
@@ -147,7 +148,7 @@ macro_rules! impl_vector_element_for_primitive {
             unsafe fn __get_unchecked(v: &CxxVector<$ty>, pos: usize) -> &$ty {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$std$vector$", stringify!($ty), "$get_unchecked")]
+                        #[link_name = concat!("cxxbridge03$std$vector$", $segment, "$get_unchecked")]
                         fn __get_unchecked(_: &CxxVector<$ty>, _: usize) -> *const $ty;
                     }
                 }
@@ -156,7 +157,7 @@ macro_rules! impl_vector_element_for_primitive {
             fn __unique_ptr_null() -> *mut c_void {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", stringify!($ty), "$null")]
+                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", $segment, "$null")]
                         fn __unique_ptr_null(this: *mut *mut c_void);
                     }
                 }
@@ -167,7 +168,7 @@ macro_rules! impl_vector_element_for_primitive {
             unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> *mut c_void {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", stringify!($ty), "$raw")]
+                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", $segment, "$raw")]
                         fn __unique_ptr_raw(this: *mut *mut c_void, raw: *mut CxxVector<$ty>);
                     }
                 }
@@ -178,7 +179,7 @@ macro_rules! impl_vector_element_for_primitive {
             unsafe fn __unique_ptr_get(repr: *mut c_void) -> *const CxxVector<Self> {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", stringify!($ty), "$get")]
+                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", $segment, "$get")]
                         fn __unique_ptr_get(this: *const *mut c_void) -> *const CxxVector<$ty>;
                     }
                 }
@@ -187,7 +188,7 @@ macro_rules! impl_vector_element_for_primitive {
             unsafe fn __unique_ptr_release(mut repr: *mut c_void) -> *mut CxxVector<Self> {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", stringify!($ty), "$release")]
+                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", $segment, "$release")]
                         fn __unique_ptr_release(this: *mut *mut c_void) -> *mut CxxVector<$ty>;
                     }
                 }
@@ -196,7 +197,7 @@ macro_rules! impl_vector_element_for_primitive {
             unsafe fn __unique_ptr_drop(mut repr: *mut c_void) {
                 extern "C" {
                     attr! {
-                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", stringify!($ty), "$drop")]
+                        #[link_name = concat!("cxxbridge03$unique_ptr$std$vector$", $segment, "$drop")]
                         fn __unique_ptr_drop(this: *mut *mut c_void);
                     }
                 }
@@ -206,6 +207,12 @@ macro_rules! impl_vector_element_for_primitive {
     };
 }
 
+macro_rules! impl_vector_element_for_primitive {
+    ($ty:ident) => {
+        impl_vector_element!(stringify!($ty), stringify!($ty), $ty);
+    };
+}
+
 impl_vector_element_for_primitive!(u8);
 impl_vector_element_for_primitive!(u16);
 impl_vector_element_for_primitive!(u32);
@@ -218,3 +225,5 @@ impl_vector_element_for_primitive!(i64);
 impl_vector_element_for_primitive!(isize);
 impl_vector_element_for_primitive!(f32);
 impl_vector_element_for_primitive!(f64);
+
+impl_vector_element!("string", "CxxString", CxxString);
diff --git a/syntax/check.rs b/syntax/check.rs
index 71fab3b7a..4fbc6e22d 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -130,8 +130,8 @@ fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
 
         match Atom::from(ident) {
             None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
-            | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64) => return,
-            Some(CxxString) => { /* todo */ }
+            | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64)
+            | Some(CxxString) => return,
             Some(Bool) | Some(RustString) => {}
         }
     }


Test patch:
diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs
index cb688f319..8aaac75ba 100644
--- a/tests/ffi/lib.rs
+++ b/tests/ffi/lib.rs
@@ -39,6 +39,7 @@ pub mod ffi {
         fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
         fn c_return_unique_ptr_vector_u8() -> UniquePtr<CxxVector<u8>>;
         fn c_return_unique_ptr_vector_f64() -> UniquePtr<CxxVector<f64>>;
+        fn c_return_unique_ptr_vector_string() -> UniquePtr<CxxVector<CxxString>>;
         fn c_return_unique_ptr_vector_shared() -> UniquePtr<CxxVector<Shared>>;
         fn c_return_unique_ptr_vector_opaque() -> UniquePtr<CxxVector<C>>;
         fn c_return_ref_vector(c: &C) -> &CxxVector<u8>;
@@ -62,6 +63,7 @@ pub mod ffi {
         fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
         fn c_take_unique_ptr_vector_u8(v: UniquePtr<CxxVector<u8>>);
         fn c_take_unique_ptr_vector_f64(v: UniquePtr<CxxVector<f64>>);
+        fn c_take_unique_ptr_vector_string(v: UniquePtr<CxxVector<CxxString>>);
         fn c_take_unique_ptr_vector_shared(v: UniquePtr<CxxVector<Shared>>);
         fn c_take_ref_vector(v: &CxxVector<u8>);
         fn c_take_rust_vec(v: Vec<u8>);
diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc
index b45e8aecc..d45d5d536 100644
--- a/tests/ffi/tests.cc
+++ b/tests/ffi/tests.cc
@@ -88,6 +88,11 @@ std::unique_ptr<std::vector<double>> c_return_unique_ptr_vector_f64() {
   return vec;
 }
 
+std::unique_ptr<std::vector<std::string>> c_return_unique_ptr_vector_string() {
+  return std::unique_ptr<std::vector<std::string>>(
+      new std::vector<std::string>());
+}
+
 std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared() {
   auto vec = std::unique_ptr<std::vector<Shared>>(new std::vector<Shared>());
   vec->push_back(Shared{1010});
@@ -210,6 +215,12 @@ void c_take_unique_ptr_vector_f64(std::unique_ptr<std::vector<double>> v) {
   }
 }
 
+void c_take_unique_ptr_vector_string(
+    std::unique_ptr<std::vector<std::string>> v) {
+  (void)v;
+  cxx_test_suite_set_correct();
+}
+
 void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v) {
   if (v->size() == 2) {
     cxx_test_suite_set_correct();
diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h
index 0efbd624d..f3bc2dd5f 100644
--- a/tests/ffi/tests.h
+++ b/tests/ffi/tests.h
@@ -43,6 +43,7 @@ rust::String c_return_rust_string();
 std::unique_ptr<std::string> c_return_unique_ptr_string();
 std::unique_ptr<std::vector<uint8_t>> c_return_unique_ptr_vector_u8();
 std::unique_ptr<std::vector<double>> c_return_unique_ptr_vector_f64();
+std::unique_ptr<std::vector<std::string>> c_return_unique_ptr_vector_string();
 std::unique_ptr<std::vector<Shared>> c_return_unique_ptr_vector_shared();
 std::unique_ptr<std::vector<C>> c_return_unique_ptr_vector_opaque();
 const std::vector<uint8_t> &c_return_ref_vector(const C &c);
@@ -67,6 +68,8 @@ void c_take_rust_string(rust::String s);
 void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
 void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v);
 void c_take_unique_ptr_vector_f64(std::unique_ptr<std::vector<double>> v);
+void c_take_unique_ptr_vector_string(
+    std::unique_ptr<std::vector<std::string>> v);
 void c_take_unique_ptr_vector_shared(std::unique_ptr<std::vector<Shared>> v);
 void c_take_ref_vector(const std::vector<uint8_t> &v);
 void c_take_rust_vec(rust::Vec<uint8_t> v);