CFFI down casting to Trait

OK, now we're getting somewhere. You might try:

pub extern "C" fn model_new(name: *const libc::c_char) -> *mut Box<Trait> {
    let my_model: Model = ...;
    Box::into_raw(Box::new(Box::new(my_model) as Box<Trait>))
}

pub extern "C" fn model_get(mptr: *mut Box<Trait>) -> *const T {
    let m = unsafe { &mut *mptr };
    m.get() as *const T
}

Yep, this works, with one extra modification: in the CFFI file the const Model* return type must be replaced with void*:

// const Model* model_new  (const char*);     // 'Model constructor'.
void* model_new  (const char*);     // 'trait constructor'.

So coming back to my presumptuous 'conclusion': Rust Traits can be used in extern "C" code, so long as the object implementing the trait is passed into the call as a downcast trait object and the const ImplType* is replaced with void*. Thus cffi wrapper/interface implementations can be defined (generically/efficiently) at the trait level. Thanks @BurntSushi & @birkenfeld!

To round it off: customarily you will have an ordinary constructor and downcaster:

CFFI code:

const Model* model_new       (const char*);  // constructor.
void*        model_as_trait  (const Model*); // downcaster.

Rust code:

#[no_mangle]
pub extern "C" fn model_new(name: *const libc::c_char) -> *const Model {

    let n = cxstring::c_char2string(name);
    let m = Model::new(&n);
    // Explicit casting not necessary:
    let t = Box::new(m);   // as Box<Model> 
    Box::into_raw(t)
}

#[no_mangle]
pub extern "C" fn model_as_trait(mptr: *mut Model) -> *mut Box<Trait> {

    let m = unsafe {
        assert!(!mptr.is_null());
        &mut *mptr
    };
    Box::into_raw(Box::new(unsafe { Box::from_raw(m) }))
}