¿Cuál es la forma correcta de pasar de un String a un * const i8?

En mi actual saga de escribir unenvoltura segura Para elControlador Cassandra C ++, ahora mi ojo se vuelve hacia evitar pérdidas de memoria al llamar a funciones C con firmas como:

cass_string_init2(const char* data, cass_size_t length);

o

cass_string_init(const char* null_terminated);

He intentado algunos enfoques diferentes que nominalmente funcionan y producen un resultado correcto, pero no he encontrado una manera de administrar la vida útil de estos datos correctamente. A continuación se presentan dos enfoques de ejemplo.

pub fn str_to_ref(mystr:&str) -> *const i8 {unsafe{
    let cstr = CString::from_slice(mystr.as_bytes());
    cstr.as_slice().as_ptr()
}}

y

pub fn str_to_ref(mystr: &str) -> *const i8 {
    let l = mystr.as_bytes();
    unsafe {
        let b = alloc::heap::allocate(mystr.len()+1, 8);
        let s = slice::from_raw_parts_mut(b, mystr.len()+1);
        slice::bytes::copy_memory(s, l);
        s[mystr.len()] = 0;
        return b as *const i8;
    }
}

El primero hace accesos de memoria no válidos como

==26355==  Address 0x782d140 is 0 bytes inside a block of size 320 free'd
==26355==    at 0x1361A8: je_valgrind_freelike_block (in /home/tupshin/workspaces/rust/cql-ffi/target/basic)
==26355==    by 0x11272D: heap::imp::deallocate::h7b540039fbffea4dPha (in /home/tupshin/workspaces/rust/cql-ffi/target/basic)
==26355==    by 0x112679: heap::deallocate::h3897fed87b942253tba (in /home/tupshin/workspaces/rust/cql-ffi/target/basic)
==26355==    by 0x112627: vec::dealloc::h7978768019700822177 (in /home/tupshin/workspaces/rust/cql-ffi/target/basic)
==26355==    by 0x112074: vec::Vec$LT$T$GT$.Drop::drop::h239007174869221309 (in /home/tupshin/workspaces/rust/cql-ffi/target/basic)
==26355==    by 0x111F9D: collections..vec..Vec$LT$i8$GT$::glue_drop.5732::h978a83960ecb86a4 (in /home/tupshin/workspaces/rust/cql-ffi/target/basic)
==26355==    by 0x111F6D: std..ffi..c_str..CString::glue_drop.5729::h953a595760f34a9d (in /home/tupshin/workspaces/rust/cql-ffi/target/basic)
==26355==    by 0x112903: cql_ffi::helpers::str_to_ref::hef3994fa55168b90bqd (in /home/tupshin/workspaces/rust/cql-ffi/target/basic)
=

mientras que el segundo no sabe cuándo desasignar su memoria, lo que resulta en:

==29782== 8 bytes in 1 blocks are definitely lost in loss record 1 of 115
==29782==    at 0x12A5B2: je_mallocx (in /home/tupshin/workspaces/rust/cql-ffi/target/basic)
==29782==    by 0x1142D5: heap::imp::allocate::h3fa8a1c097e9ea53Tfa (in /home/tupshin/workspaces/rust/cql-ffi/target/basic)
==29782==    by 0x114221: heap::allocate::h18d191ce51ab2236gaa (in /home/tupshin/workspaces/rust/cql-ffi/target/basic)
==29782==    by 0x112874: cql_ffi::helpers::str_to_ref::h5b60f207d1e31841bqd (helpers.rs:25)

Utilizando cualquiera de esos dos enfoques como punto de partida, o algo completamente diferente, realmente agradecería alguna orientación sobre una forma adecuada de lograr esto.

Editar:

La respuesta de Shepperfectamente resolvió mis problemas usando cass_string_init y cass_string_init2. Muchas gracias. Sin embargo, todavía no estoy claro al pasar * const i8 params a otras funciones como:

CASS_EXPORT CassError
cass_cluster_set_contact_points(CassCluster* cluster,
const char* contact_points);

que esperan pasar una referencia a una cadena terminada en nulo.

Basado en el enfoque anterior que funcionó para CassStrings, junto con los documentos de CString, se me ocurrió lo siguiente:

pub struct ContactPoints(*const c_char);

pub trait AsContactPoints {
    fn as_contact_points(&self) -> ContactPoints;
}

impl AsContactPoints for str {
    fn as_contact_points(&self) -> ContactPoints {
        let cstr = CString::new(self).unwrap();
        let bytes = cstr.as_bytes_with_nul();
        let ptr = bytes.as_ptr();
        ContactPoints(ptr as *const i8)
    }
}

(Los excesivos enlaces permitidos son solo para asegurarse de que no me falte ninguna sutileza)

y eso funciona correctamente, pero valgrind se queja:

==22043== Invalid read of size 1
==22043==    at 0x4C2E0E2: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22043==    by 0x4F8AED8: cass_cluster_set_contact_points (in /usr/local/lib/libcassandra.so.1.0.0)
==22043==    by 0x11367A: cql_ffi::cluster::CassCluster::set_contact_points::h575496cbf7644b9e6oa (cluster.rs:76)

Respuestas a la pregunta(1)

Su respuesta a la pregunta