代码之家  ›  专栏  ›  技术社区  ›  Rich

创建一个rust共享库,该库将函数指针的结构返回给c主程序

  •  0
  • Rich  · 技术社区  · 6 年前

    我想在没有太多运气的情况下把锈粘在NBDKIT上。我要做一个 .so 文件,这很简单。这个 所以 文件必须有一个名为 plugin_init ,也很简单。但是,此函数必须返回指向c兼容的指针 struct 包含字符串和函数指针的混合(C主程序稍后将调用)。

    API是: https://github.com/libguestfs/nbdkit/blob/409ce4c9238a84ede6688423b20d5f706067834b/include/nbdkit-plugin.h#L53

    我想到了:

    #[repr(C)]
    pub struct NBDKitPlugin {
        _struct_size: uint64_t,
        _api_version: c_int,
        _thread_model: c_int,
    
        name: *const c_char,
        longname: Option<*const c_char>,
        version: Option<*const c_char>,
        description: Option<*const c_char>,
    
        load: Option<extern fn ()>,
        unload: Option<extern fn ()>,
    
        config: Option<extern fn ()>, // XXX
        config_complete: Option<extern fn () -> c_int>,
        config_help: Option<*const c_char>,
    
        open: extern fn (c_int) -> *mut c_void,
        close: Option<extern fn (*mut c_void)>,
    }
    

    和A 小精灵 功能:

    extern fn hello_load () {
        println! ("hello this is the load method");
    }
    
    struct MyHandle {
    }
    
    extern fn hello_open (readonly: c_int) -> *mut c_void {
        println! ("hello, this is the open method");
        let mut h = MyHandle {};
        let vp: *mut c_void = &mut h as *mut _ as *mut c_void;
        return vp;
    }
    
    #[no_mangle]
    pub extern fn plugin_init () -> *const NBDKitPlugin {
        println! ("hello from the plugin");
    
        let plugin = Box::new (NBDKitPlugin {
            _struct_size: mem::size_of::<NBDKitPlugin>() as uint64_t,
            _api_version: 2,
            _thread_model: 3,
            name: CString::new("hello").unwrap().into_raw(),
            longname: None,
            version: None,
            description: None,
            load: Some (hello_load),
            unload: None,
            config: None,
            config_complete: None,
            config_help: Some (CString::new("my config_help here").unwrap().into_raw()),
            open: hello_open,
            close: None,
        });
    
        return Box::into_raw(plugin);
    }
    

    除了泄漏内存,这部分工作。整数和字符串是从c ok中看到的。但是函数指针根本不起作用。它们完全是假的,似乎比原始指针占用更多的空间,所以我想我暴露了一个“胖”锈指针。

    关于这个主题,我几乎找不到什么文档。帮助。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Francis Gagné    6 年前

    你可能在某个时候了解到( &T )包裹在 Option ( Option<&T> )进行了优化,以便 None 编码为所有零,这对引用无效,并且 选项<t> 大小与 &T .

    但是,对于原始指针,所有零都是有效的位模式( *const T *mut T ):它表示空指针。因此,用 选择权 和包装没什么区别,比如说 i32 在一个 选择权 : 选择权 类型更大,以便可以存储鉴别器。

    若要修复结构定义,不能使用 选择权 定义 longname , version description .