1{{#title *mut T, *const T — Rust ♡ C++}} 2# *mut T, *const T 3 4Generally you should use references (`&mut T`, `&T`) or [std::unique_ptr\<T\>] 5where possible over raw pointers, but raw pointers are available too as an 6unsafe fallback option. 7 8[std::unique_ptr\<T\>]: uniqueptr.md 9 10### Restrictions: 11 12Extern functions and function pointers taking a raw pointer as an argument must 13be declared `unsafe fn` i.e. unsafe to call. The same does not apply to 14functions which only *return* a raw pointer, though presumably doing anything 15useful with the returned pointer is going to involve unsafe code elsewhere 16anyway. 17 18## Example 19 20This example illustrates making a Rust call to a canonical C-style `main` 21signature involving `char *argv[]`. 22 23```cpp 24// include/args.h 25 26#pragma once 27 28void parseArgs(int argc, char *argv[]); 29``` 30 31```cpp 32// src/args.cc 33 34#include "example/include/args.h" 35#include <iostream> 36 37void parseArgs(int argc, char *argv[]) { 38 std::cout << argc << std::endl; 39 for (int i = 0; i < argc; i++) { 40 std::cout << '"' << argv[i] << '"' << std::endl; 41 } 42} 43``` 44 45```rust,noplayground 46// src/main.rs 47 48use std::env; 49use std::ffi::CString; 50use std::os::raw::c_char; 51use std::os::unix::ffi::OsStrExt; 52use std::ptr; 53 54#[cxx::bridge] 55mod ffi { 56 extern "C++" { 57 include!("example/include/args.h"); 58 59 unsafe fn parseArgs(argc: i32, argv: *mut *mut c_char); 60 } 61} 62 63fn main() { 64 // Convert from OsString to nul-terminated CString, truncating each argument 65 // at the first inner nul byte if present. 66 let args: Vec<CString> = env::args_os() 67 .map(|os_str| { 68 let bytes = os_str.as_bytes(); 69 CString::new(bytes).unwrap_or_else(|nul_error| { 70 let nul_position = nul_error.nul_position(); 71 let mut bytes = nul_error.into_vec(); 72 bytes.truncate(nul_position); 73 CString::new(bytes).unwrap() 74 }) 75 }) 76 .collect(); 77 78 // Convert from Vec<CString> of owned strings to Vec<*mut c_char> of 79 // borrowed string pointers. 80 // 81 // Once extern type stabilizes (https://github.com/rust-lang/rust/issues/43467) 82 // and https://internals.rust-lang.org/t/pre-rfc-make-cstr-a-thin-pointer/6258 83 // is implemented, and CStr pointers become thin, we can sidestep this step 84 // by accumulating the args as Vec<Box<CStr>> up front, then simply casting 85 // from *mut [Box<CStr>] to *mut [*mut CStr] to *mut *mut c_char. 86 let argc = args.len(); 87 let mut argv: Vec<*mut c_char> = Vec::with_capacity(argc + 1); 88 for arg in &args { 89 argv.push(arg.as_ptr() as *mut c_char); 90 } 91 argv.push(ptr::null_mut()); // Nul terminator. 92 93 unsafe { 94 ffi::parseArgs(argc as i32, argv.as_mut_ptr()); 95 } 96 97 // The CStrings go out of scope here. C function must not have held on to 98 // the pointers beyond this point. 99} 100``` 101