Skip to content

Commit 71c7b45

Browse files
authored
Merge pull request #515 from dtolnay/c_char
Support c_char type
2 parents 248215e + 93e71d0 commit 71c7b45

File tree

13 files changed

+54
-22
lines changed

13 files changed

+54
-22
lines changed

gen/src/write.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ fn pick_includes_and_builtins(out: &mut OutFile, apis: &[Api]) {
159159
Some(Isize) => out.builtin.rust_isize = true,
160160
Some(CxxString) => out.include.string = true,
161161
Some(RustString) => out.builtin.rust_string = true,
162-
Some(Bool) | Some(F32) | Some(F64) | None => {}
162+
Some(Bool) | Some(Char) | Some(F32) | Some(F64) | None => {}
163163
},
164164
Type::RustBox(_) => out.builtin.rust_box = true,
165165
Type::RustVec(_) => out.builtin.rust_vec = true,
@@ -924,6 +924,7 @@ fn write_type(out: &mut OutFile, ty: &Type) {
924924
fn write_atom(out: &mut OutFile, atom: Atom) {
925925
match atom {
926926
Bool => write!(out, "bool"),
927+
Char => write!(out, "char"),
927928
U8 => write!(out, "uint8_t"),
928929
U16 => write!(out, "uint16_t"),
929930
U32 => write!(out, "uint32_t"),

src/cxx.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,7 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
379379
#define FOR_EACH_RUST_VEC(MACRO) \
380380
FOR_EACH_NUMERIC(MACRO) \
381381
MACRO(bool, bool) \
382+
MACRO(char, char) \
382383
MACRO(string, rust::String)
383384

384385
extern "C" {

src/symbols/rust_vec.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::rust_vec::RustVec;
33
use alloc::vec::Vec;
44
use core::mem;
55
use core::ptr;
6+
use std::os::raw::c_char;
67

78
macro_rules! rust_vec_shims {
89
($segment:expr, $ty:ty) => {
@@ -74,4 +75,5 @@ rust_vec_shims_for_primitive!(i64);
7475
rust_vec_shims_for_primitive!(f32);
7576
rust_vec_shims_for_primitive!(f64);
7677

78+
rust_vec_shims!("char", c_char);
7779
rust_vec_shims!("string", RustString);

syntax/atom.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::fmt::{self, Display};
55
#[derive(Copy, Clone, PartialEq)]
66
pub enum Atom {
77
Bool,
8+
Char, // C char, not Rust char
89
U8,
910
U16,
1011
U32,
@@ -30,6 +31,7 @@ impl Atom {
3031
use self::Atom::*;
3132
match s {
3233
"bool" => Some(Bool),
34+
"c_char" => Some(Char),
3335
"u8" => Some(U8),
3436
"u16" => Some(U16),
3537
"u32" => Some(U32),
@@ -60,6 +62,7 @@ impl AsRef<str> for Atom {
6062
use self::Atom::*;
6163
match self {
6264
Bool => "bool",
65+
Char => "c_char",
6366
U8 => "u8",
6467
U16 => "u16",
6568
U32 => "u32",

syntax/check.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
9999
}
100100

101101
match Atom::from(&ident.rust) {
102-
None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
103-
| Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64)
104-
| Some(RustString) => return,
102+
None | Some(Char) | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize)
103+
| Some(I8) | Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32)
104+
| Some(F64) | Some(RustString) => return,
105105
Some(Bool) => { /* todo */ }
106106
Some(CxxString) => {}
107107
}
@@ -140,6 +140,7 @@ fn check_type_cxx_vector(cx: &mut Check, ptr: &Ty1) {
140140
None | Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(Usize) | Some(I8)
141141
| Some(I16) | Some(I32) | Some(I64) | Some(Isize) | Some(F32) | Some(F64)
142142
| Some(CxxString) => return,
143+
Some(Char) => { /* todo */ }
143144
Some(Bool) | Some(RustString) => {}
144145
}
145146
}
@@ -503,6 +504,8 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
503504
"opaque Rust type".to_owned()
504505
} else if Atom::from(&ident.rust) == Some(CxxString) {
505506
"C++ string".to_owned()
507+
} else if Atom::from(&ident.rust) == Some(Char) {
508+
"C char".to_owned()
506509
} else {
507510
ident.rust.to_string()
508511
}

syntax/tokens.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ impl ToTokens for Type {
1111
fn to_tokens(&self, tokens: &mut TokenStream) {
1212
match self {
1313
Type::Ident(ident) => {
14-
if ident.rust == CxxString {
14+
if ident.rust == Char {
15+
let span = ident.rust.span();
16+
tokens.extend(quote_spanned!(span=> ::std::os::raw::));
17+
} else if ident.rust == CxxString {
1518
let span = ident.rust.span();
1619
tokens.extend(quote_spanned!(span=> ::cxx::));
1720
}

tests/BUCK

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ rust_test(
1212
rust_library(
1313
name = "ffi",
1414
srcs = [
15+
"ffi/cast.rs",
1516
"ffi/lib.rs",
1617
"ffi/module.rs",
1718
],

tests/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ rust_test(
1515
rust_library(
1616
name = "cxx_test_suite",
1717
srcs = [
18+
"ffi/cast.rs",
1819
"ffi/lib.rs",
1920
"ffi/module.rs",
2021
],

tests/ffi/cast.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
use std::os::raw::c_char;
2+
use std::slice;
3+
4+
pub fn c_char_to_unsigned(slice: &[c_char]) -> &[u8] {
5+
let ptr = slice.as_ptr().cast::<u8>();
6+
let len = slice.len();
7+
unsafe { slice::from_raw_parts(ptr, len) }
8+
}
9+
10+
pub fn unsigned_to_c_char(slice: &[u8]) -> &[c_char] {
11+
let ptr = slice.as_ptr().cast::<c_char>();
12+
let len = slice.len();
13+
unsafe { slice::from_raw_parts(ptr, len) }
14+
}

tests/ffi/lib.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66
clippy::unnecessary_wraps
77
)]
88

9+
pub mod cast;
910
pub mod module;
1011

1112
use cxx::{CxxString, CxxVector, UniquePtr};
1213
use std::fmt::{self, Display};
14+
use std::os::raw::c_char;
1315

1416
#[cxx::bridge(namespace = "tests")]
1517
pub mod ffi {
@@ -81,7 +83,7 @@ pub mod ffi {
8183
fn c_return_ref(shared: &Shared) -> &usize;
8284
fn c_return_mut(shared: &mut Shared) -> &mut usize;
8385
fn c_return_str(shared: &Shared) -> &str;
84-
fn c_return_sliceu8(shared: &Shared) -> &[u8];
86+
fn c_return_slice_char(shared: &Shared) -> &[c_char];
8587
fn c_return_mutsliceu8(slice: &mut [u8]) -> &mut [u8];
8688
fn c_return_rust_string() -> String;
8789
fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
@@ -110,7 +112,7 @@ pub mod ffi {
110112
fn c_take_ref_r(r: &R);
111113
fn c_take_ref_c(c: &C);
112114
fn c_take_str(s: &str);
113-
fn c_take_sliceu8(s: &[u8]);
115+
fn c_take_slice_char(s: &[c_char]);
114116
fn c_take_slice_shared(s: &[Shared]);
115117
fn c_take_rust_string(s: String);
116118
fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
@@ -214,7 +216,7 @@ pub mod ffi {
214216
fn r_take_ref_r(r: &R);
215217
fn r_take_ref_c(c: &C);
216218
fn r_take_str(s: &str);
217-
fn r_take_sliceu8(s: &[u8]);
219+
fn r_take_slice_char(s: &[c_char]);
218220
fn r_take_rust_string(s: String);
219221
fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
220222
fn r_take_ref_vector(v: &CxxVector<u8>);
@@ -472,8 +474,9 @@ fn r_take_rust_string(s: String) {
472474
assert_eq!(s, "2020");
473475
}
474476

475-
fn r_take_sliceu8(s: &[u8]) {
477+
fn r_take_slice_char(s: &[c_char]) {
476478
assert_eq!(s.len(), 5);
479+
let s = cast::c_char_to_unsigned(s);
477480
assert_eq!(std::str::from_utf8(s).unwrap(), "2020\0");
478481
}
479482

0 commit comments

Comments
 (0)