-
Notifications
You must be signed in to change notification settings - Fork 338
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add API to get slice from CxxVector #321
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -841,6 +841,7 @@ fn expand_cxx_vector(namespace: &Namespace, elem: &Ident) -> TokenStream { | |
let name = elem.to_string(); | ||
let prefix = format!("cxxbridge04$std$vector${}{}$", namespace, elem); | ||
let link_size = format!("{}size", prefix); | ||
let link_data = format!("{}data", prefix); | ||
let link_get_unchecked = format!("{}get_unchecked", prefix); | ||
let unique_ptr_prefix = format!("cxxbridge04$unique_ptr$std$vector${}{}$", namespace, elem); | ||
let link_unique_ptr_null = format!("{}null", unique_ptr_prefix); | ||
|
@@ -859,6 +860,16 @@ fn expand_cxx_vector(namespace: &Namespace, elem: &Ident) -> TokenStream { | |
} | ||
unsafe { __vector_size(v) } | ||
} | ||
fn __vector_slice(v: &::cxx::CxxVector<Self>) -> &[Self] { | ||
extern "C" { | ||
#[link_name = #link_size] | ||
fn __vector_size(_: &::cxx::CxxVector<#elem>) -> usize; | ||
#[link_name = #link_data] | ||
fn __vector_data(_: &::cxx::CxxVector<#elem>) -> *const #elem; | ||
} | ||
let ret = unsafe { std::slice::from_raw_parts(__vector_data(v), __vector_size(v)) }; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe this is undefined behavior in the case that size is 0. The data ptr of a &[T] has to be nonnull and properly aligned regardless of size, which C++ does not guarantee. See https://doc.rust-lang.org/std/slice/fn.from_raw_parts.html#safety. Somewhere there will need to be special handling of the empty vector case. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was actually wondering about that. ;) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Have not looked into how rust handles alignment. That could be a biggie if rust has different alignment reqs... Having said that, we could enforce that in the __vector_data() implementation. As in, if wrongly aligned, "do something". that "do something" needs looking into/discussion. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed handling of null data() ptr. UB only happens if std::vector's capacity() is 0 if I got the from_raw_parts documentation right. There does not seem to be a need to specifically handle 0 size. Famous last words? Ignore my going off the tangent with non-alignment. I was thinking off T, whereas you were talking about the data ptr if null. |
||
ret | ||
} | ||
unsafe fn __get_unchecked(v: &::cxx::CxxVector<Self>, pos: usize) -> &Self { | ||
extern "C" { | ||
#[link_name = #link_get_unchecked] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -401,6 +401,12 @@ extern "C" const char *cxx_run_test() noexcept { | |
std::unique_ptr<std::string>(new std::string("2020"))); | ||
r_take_enum(Enum::AVal); | ||
|
||
// Caller owns data handed into rust APIs | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Test for that did not really fit into the "take" or "return" tests. I initially had a c_take...() test that would create a std::vector and then call into the r_access_...() test function, but I found that overly complex as the c_take...() test did not add anything. Hence, directly testing the API in r_access..() here. |
||
{ | ||
std::vector<std::uint8_t> v{86, 75, 30, 9}; | ||
r_access_vector_u8_as_slice(v); | ||
} | ||
|
||
ASSERT(r_try_return_primitive() == 2020); | ||
try { | ||
r_fail_return_primitive(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wondering whether I can or should generate src/cxx.h|cc from this. Need to look into that...