Biblioteca C liberando un puntero proveniente de Rust

Quiero hacer enlaces Rust a una biblioteca de C que requiera una devolución de llamada, y esta devolución de llamada debe devolver un estilo Cchar* puntero a la biblioteca C que luego lo liberará. La devolución de llamada debe estar en cierto sentido expuesta al usuario de mi biblioteca (probablemente usando cierres), y quiero proporcionar una interfaz Rust lo más conveniente posible (es decir, aceptar unString salida si es posible).

Sin embargo, la biblioteca C se queja cuando intentafree() un puntero que proviene de la memoria asignada por Rust, probablemente porque Rust usa jemalloc y la biblioteca C usa malloc.

Así que actualmente puedo ver dos soluciones usandolibc::malloc(), pero ambos tienen desventajas:

Dele al usuario de la biblioteca una porción que debe llenar (inconveniente e impone restricciones de longitud)Toma suString salida, cópielo en una matriz asignada por malloc y luego libere elString (copia inútil y asignación)

¿Alguien puede ver una mejor solución?

Aquí hay un equivalente de la interfaz de la biblioteca C y la implementación del caso ideal (si la biblioteca C pudiera liberar una Cadena asignada en Rust)

extern crate libc;
use std::ffi::CString;
use libc::*;
use std::mem;

extern "C" {
    // The second parameter of this function gets passed as an argument of my callback
    fn need_callback(callback: extern fn(arbitrary_data: *mut c_void) -> *mut c_char,
                     arbitrary_data: *mut c_void);
}

// This function must return a C-style char[] that will be freed by the C library
extern fn my_callback(arbitrary_data: *mut c_void) -> *mut c_char {
    unsafe {
        let mut user_callback: *mut &'static mut FnMut() -> String = mem::transmute(arbitrary_data); //'
        let user_string = (*user_callback)();
        let c_string = CString::new(user_string).unwrap();
        let ret: *mut c_char = mem::transmute(c_string.as_ptr());
        mem::forget(c_string); // To prevent deallocation by Rust
        ret
    }
}

pub fn call_callback(mut user_callback: &mut FnMut() -> String) {
    unsafe {
        need_callback(my_callback, mem::transmute(&mut user_callback));
    }
}

La parte C sería equivalente a esto:

#include <stdlib.h>
typedef char* (*callback)(void *arbitrary_data);
void need_callback(callback cb, void *arbitrary_data) {
    char *user_return = cb(arbitrary_data);
    free(user_return); // Complains as the pointer has been allocated with jemalloc
}

Respuestas a la pregunta(1)

Su respuesta a la pregunta