Expand description
Safe, zero-copy wrapper for passing string arrays to C FFI (char**
)
This crate provides CStringArray
, a safe abstraction over C’s
null-terminated string arrays, commonly used for command-line arguments and
similar purposes.
§Features
- Memory-safe: RAII-based lifetime management prevents dangling pointers
- Zero-copy: When constructed from
Vec<CString>
, no re-allocation occurs - C-compatible: Produces valid
char**
pointers with null termination - Ergonomic: Multiple constructors and trait implementations for easy usage
- Well-tested: Comprehensive test coverage for reliability
§Example
use std::ffi::c_char;
use cstring_array::CStringArray;
let args = vec![
"program".to_string(),
"--verbose".to_string(),
"file.txt".to_string(),
];
let array = CStringArray::new(args).unwrap();
// Safe to pass to C FFI functions expecting char**
let ptr: *const *const c_char = array.as_ptr();
assert_eq!(array.len(), 3);
§Creating Arrays
Multiple ways to construct a CStringArray
:
use std::{convert::TryFrom, ffi::CString};
use cstring_array::CStringArray;
// From Vec<String>
let arr1 = CStringArray::new(vec!["foo".to_string(), "bar".to_string()]).unwrap();
// From Vec<CString> (zero-copy)
let cstrings = vec![CString::new("foo").unwrap(), CString::new("bar").unwrap()];
let arr2 = CStringArray::from_cstrings(cstrings).unwrap();
// Using TryFrom with Vec<&str>
let arr3 = CStringArray::try_from(vec!["foo", "bar"]).unwrap();
// Using TryFrom with arrays
let arr4 = CStringArray::try_from(["foo", "bar"]).unwrap();
// Using FromIterator (collect)
let arr5: CStringArray = vec!["a", "b", "c"].into_iter().map(String::from).collect();
§Trait Implementations
CStringArray
implements many standard Rust traits for ergonomic usage:
use std::collections::HashMap;
use cstring_array::CStringArray;
let arr1 = CStringArray::new(vec!["a".to_string(), "b".to_string()]).unwrap();
// Clone
let arr2 = arr1.clone();
assert_eq!(arr1, arr2);
// Equality
assert_eq!(arr1, arr2);
// Hash (use in HashMap)
let mut map = HashMap::new();
map.insert(arr1.clone(), "value");
// Indexing
assert_eq!(arr1[0].to_str().unwrap(), "a");
assert_eq!(arr1[1].to_str().unwrap(), "b");
// Iteration (borrowed)
for s in &arr1 {
println!("{}", s.to_str().unwrap());
}
// Iteration (owned)
for s in arr2 {
println!("{}", s.to_str().unwrap());
}
// AsRef conversion
fn process_strings(strings: &[std::ffi::CString]) {
println!("Processing {} strings", strings.len());
}
process_strings(arr1.as_ref());
§Safety Considerations
The pointer returned by CStringArray::as_ptr
is only valid for the
lifetime of the CStringArray
. Ensure the array outlives any C code using
the pointer:
use std::ffi::c_char;
use cstring_array::CStringArray;
fn call_c_function(argv: *const *const c_char, argc: i32) {
// ... FFI call ...
}
let array = CStringArray::new(vec!["arg1".to_string(), "arg2".to_string()]).unwrap();
let ptr = array.as_ptr();
call_c_function(ptr, array.len() as i32);
// array must not be dropped before call_c_function returns
Structs§
- CString
Array - Safe wrapper for passing string arrays to C FFI as
char**
.
Enums§
- CString
Array Error - Error type for CStringArray operations