代码之家  ›  专栏  ›  技术社区  ›  Florian Doyon

Impl Send for Bindgen生成的指针类型

  •  -1
  • Florian Doyon  · 技术社区  · 6 年前

    from opensles-sys

    这是我的包装结构:

    pub struct AndroidAudioIO {
        sl_output_buffer_queue: NonNull<SLObjectItf>,
    }
    unsafe impl Send for AndroidAudioIO{}
    

    SLObjectItf 类型是的别名 *const *const SLObjectItf_ 其定义由bindgen生成。它是FFI函数指针的集合。

    #[repr(C)]
    #[derive(Debug, Copy, Clone)]
    pub struct SLObjectItf_ {
        pub Realize: ::std::option::Option<
            unsafe extern "C" fn(self_: SLObjectItf, async: SLboolean) -> SLresult,
        >,
        // More of the same pattern, only extern "C" function pointers, no data
    }
    

    我试着添加 unsafe impl Send for SLObjectItf_{} 其他的变种也没有用。

    error[E0277]: `std::ptr::NonNull<*const *const opensles::bindings::SLObjectItf_>` cannot be shared between threads safely
      --> src/lib.rs:12:1
       |
    12 | / lazy_static! {
    13 | | static ref engine:Option<mynoise::Engine<Box<audio::AndroidAudioIO>>> = None;
    14 | | }
       | |_^ `std::ptr::NonNull<*const *const opensles::bindings::SLObjectItf_>` cannot be shared between threads safely
       |
       = help: within `audio::AndroidAudioIO`, the trait `std::marker::Sync` is not implemented for `std::ptr::NonNull<*const *const opensles::bindings::SLObjectItf_>`
       = note: required because it appears within the type `audio::AndroidAudioIO`
    

    Send Sync 发送

    1 回复  |  直到 6 年前
        1
  •  2
  •   E_net4 Tunn    6 年前

    下面的代码再现了相同的问题(假设 Engine AndroidAudioIO 在类型级别,以便以后可以生成这样的处理程序;它也通过直接合成来工作)。

    #[macro_use]
    extern crate lazy_static;
    
    use std::marker::PhantomData;
    use std::ptr::NonNull;
    
    #[repr(C)]
    #[derive(Debug, Copy, Clone)]
    pub struct SLObjectItf;
    
    pub struct AndroidAudioIO {
        sl_output_buffer_queue: NonNull<SLObjectItf>,
    }
    unsafe impl Send for AndroidAudioIO {}
    
    #[derive(Debug)]
    pub struct Engine<T>(PhantomData<T>);
    
    lazy_static! {
        static ref engine: Option<Engine<AndroidAudioIO>> = None;
    }
    

    ( Playground

    发动机 实体位于全局静态变量中,这会立即使它在所有线程中共享。这需要 Sync 没有得到执行 同步 因为 AudioAndroidIO 不执行 同步 PhantomData 直接从其参数类型继承这些trait实现。引用文件:

    impl<T: ?Sized> Send for PhantomData<T>
    where
        T: Send,
    impl<T: ?Sized> Sync for PhantomData<T>
    where
        T: Sync
    

    在这种情况下 发动机 可以有吗 (尽管 绝对的 同步 为了这个。

    unsafe impl<T> Sync for Engine<T> {}
    

    我试着添加 unsafe impl Send for SLObjectItf_{} 其他的变种也没有用。

    好吧,那通常是个坏主意。实施 Send 同步 应该在绑定的安全、高级抽象之上完成。