2017-02-16 18 views
4

pthread_createを後でリンクするC関数にポイントしたいと思います。そのC関数はpthread_cleanup_pushpthread_cleanup_popを使用します。これはCマクロであり、したがってRustに移植することはできません。安全でない関数をラップせずに安全関数が必要な場合、どのように安全でない関数を渡すことができますか?

これは私のコードです:

extern crate libc; 
use std::ptr::null_mut; 
use libc::c_void; 

extern "C" { 
    fn thr_fn1(arg:*mut c_void) -> *mut c_void; 
} 

fn main() { 
    let mut tid1 = std::mem::zeroed(); 
    libc::pthread_create(&mut tid1, null_mut(), thr_fn1, null_mut()); 
} 

私はとにかくのlibcのFFIを呼んでいることから、私はちょうど、外部C関数を指すことができますが、私はエラーを取得することを期待:

error[E0308]: mismatched types 
    --> src/bin/11-threads/f05-thread-cleanup.rs:25:49 
    | 
25 |  libc::pthread_create(&mut tid1, null_mut(), thr_fn1, null_mut()); 
    |             ^^^^^^^ expected normal fn, found unsafe fn 
    | 
    = note: expected type `extern "C" fn(*mut libc::c_void) -> *mut libc::c_void` 
       found type `unsafe extern "C" fn(*mut libc::c_void) -> *mut libc::c_void {thr_fn1}` 

ブロックのunsafe{}ブロックにC関数を呼び出すラッパーを書くことはできますが、それを避ける方法はありますか?

+2

を修正するためにa PR for libcを開きました。あなたはそれを書いたと思っていますか、署名を変更するように頼んだことがありますか? – Shepmaster

+1

C関数を渡すCコードを呼び出すためにRustコードを使用している場合は、Cコードから 'pthread_create'を呼び出し、すべての曲とダンスをスキップします。 – Shepmaster

+0

安全なコードだけをCに渡すように要求するのは余計に見えますが、単純な回避策は 'extern" Cを作成することです。 "fn wrapped_fn1(arg:* mut c_void) - > * mut c_void {unsafe {thr_fn1(arg)}}' 'wrapped_fn1'を' pthread_create'に渡します。また 'libc :: pthread_create'と' std :: mem :: zeroed'を呼び出すには 'main'に' unsafe'ブロックが必要です。 – user4815162342

答えて

1

libc関数定義は間違っている:Cヘッダー/usr/include/pthread.h

extern int pthread_create (pthread_t *__restrict __newthread, 
          const pthread_attr_t *__restrict __attr, 
          void *(*__start_routine) (void *), 
          void *__restrict __arg) __THROWNL __nonnull ((1, 3)); 

bindgenは、この関数の定義を生成します。MacOSのとLinuxの両方をコンパイル

pub fn pthread_create(arg1: *mut pthread_t, 
         arg2: *const pthread_attr_t, 
         arg3: Option<unsafe extern "C" fn(arg1: *mut c_void) -> *mut c_void>, 
         arg4: *mut c_void) -> c_int; 

。私は確信していませんOptionここに良いアイデアです。なぜ誰かが関数を呼び出さないスレッドを開始するのだろうか?

私はただのlibcのバグのような音の問題(Option一部なし)

+0

* bindgenは自動化されたツールであり、ポインタが 'NULL'であってはならない場合には関数のシグニチャを識別することができないので、' Option'は良い考えです。 – Shepmaster

+0

@Shepmasterだから、ここでも 'Option'を使わないように提案しますよね? – hansaplast

+0

伝えるのは難しいです。 **私はあなたがなぜそう思うかはわかりませんが、このような呼び出しは、多くの場合、エッジケースのargumnetsのオーバーロードされた動作で蔓延します。例えば、 'kill(2)'は、プロセスがPID 0を持つことができなくても、PID 0を引数として使用することを許可します。 – Shepmaster

関連する問題