環境
- Windows 10
- Rust 1.50.0
生じている問題
RustでDLLを作ってそれをほかのクレートから呼び出そうとしました。DLLを作る側は
lib.rs
rust
1use std::os::raw::{c_int, c_short, c_uchar, c_uint}; 2 3#[no_mangle] 4pub extern "C" fn TUSB0216AD_Device_Open(_id: c_short) -> c_short { 5 return 0; 6} 7 8#[no_mangle] 9pub extern "C" fn TUSB0216AD_Device_Close(_id: c_short) {} 10 11#[no_mangle] 12pub extern "C" fn TUSB0216AD_Start( 13 _id: c_short, 14 _ch: c_uchar, 15 _pre_len: c_int, 16 _trig_type: c_uchar, 17 _trig_ch: c_uchar, 18) -> c_short { 19 return 0; 20} 21 22#[no_mangle] 23pub extern "C" fn TUSB0216AD_Stop(_id: c_short) -> c_short { 24 return 0; 25} 26 27#[no_mangle] 28pub extern "C" fn TUSB0216AD_Ad_Data( 29 _id: c_short, 30 _ch: c_short, 31 _data: *mut c_int, 32 _datalen: *mut c_uint, 33) -> c_short { 34 unsafe { 35 *_data = 10; 36 *_datalen = 1; 37 } 38 39 return 0; 40} 41 42#[no_mangle] 43pub extern "C" fn TUSB0216AD_AdClk_Set(_id: c_short, _clk_time: c_int, _sel: c_uchar) -> c_short { 44 return 0; 45} 46 47#[no_mangle] 48pub extern "C" fn TUSB0216AD_Input_Set(_id: c_short, _type1: c_uchar, _type2: c_uchar) -> c_short { 49 return 0; 50} 51 52#[no_mangle] 53pub extern "C" fn TUSB0216AD_Trigger(_id: c_short) -> c_short { 54 return 0; 55} 56
生ポインタを使っていたりするのは、このDLLがもともとある装置のCインターフェースをモックするという目的で作っているためです。
これを使っている側は
lib.rs
rust
1mod helper; 2 3use std::sync::{Arc, Mutex}; 4use std::thread; 5 6#[no_mangle] 7pub extern "C" fn run(id: i32, seconds: u64) { 8 // sequence が走っているかを示すフラグ 9 // -1: not-started, 0: running, 1: finished 10 let flag = Arc::new(Mutex::new(0)); 11 const DATA_SIZE: usize = 50000; 12 13 let flg1 = Arc::clone(&flag); 14 let time_keeper = thread::spawn(move || { 15 helper::continuous_read(id, seconds, flg1); 16 }); 17 18 let flg2 = Arc::clone(&flag); 19 let mut x = vec![0.0 as f32; DATA_SIZE]; 20 let mut y = vec![0.0 as f32; DATA_SIZE]; 21 22 let job_runner = thread::spawn(move || { 23 helper::get_data(id, flg2, &mut x, &mut y); 24 }); 25 26 time_keeper.join().unwrap(); 27 job_runner.join().unwrap(); 28}
helper.rs
rust
1use std::sync::{Arc, Mutex}; 2use std::{thread, time}; 3 4#[link(name = "ad_mock.dll", kind = "dylib")] 5#[allow(dead_code)] 6extern "C" { 7 pub fn TUSB0216AD_Device_Open(id: i32) -> i32; 8 pub fn TUSB0216AD_Device_Close(id: i32); 9 /// 連続測定を開始 10 /// ch: 0 (1chのみ)、1(2chのみ)、2(1, 2ch同時) 11 /// PreLen: プレトリガ長 12 /// TrigType: トリガ種類、0: 内部トリガ、1: 外部デジタル、2: アナログ立ち上がり、3: アナログ立下り 13 /// TrigCh: アナログトリガのトリガチャネル、0: ch1, 1: ch2 14 pub fn TUSB0216AD_Start(id: i32, ch: &u8, PreLen: i32, TrigType: u8, TrgCh: u8) -> i32; 15 /// 連続取り込み停止 16 pub fn TUSB0216AD_Stop(id: i32) -> i32; 17 /// 取り込み済みデータを取得 18 /// data: 取り込みデータの格納先のポインタ 19 /// datalen: 取り込み要求長。1~262144、戻るときには実際に取得された数が入っている 20 pub fn TUSB0216AD_Ad_Data(id: i32, ch: u8, data: *mut i32, datalen: *mut u32) -> i32; 21 /// クロック時間の設定 22 /// ClkTime: 内部クロック周期設定、500 ~ 2147483647。クロック周期 = ClkTime * 20 ns 23 /// sel: クロックソース、0: 内部クロック、1: 外部クロック 24 pub fn TUSB0216AD_AdClk_Set(id: i32, ClkTime: i32, sel: u8) -> i32; 25 /// ソフトウェアトリガを掛ける 26 pub fn TUSB0216AD_Trigger(id: i32) -> i32; 27} 28 29pub fn continuous_read(id: i32, seconds: u64, flag: Arc<Mutex<i8>>) { 30 println!("Timer start!"); 31 let sleeping_time = time::Duration::from_secs(seconds); 32 33 unsafe { 34 TUSB0216AD_Input_Set(id, 0, 0); 35 TUSB0216AD_Start(id, &(2 as u8), 0, 0, 0); 36 TUSB0216AD_Trigger(id); 37 } 38 39 *flag.lock().unwrap() = 0; // 計測開始のフラグを立てる 40 thread::sleep(sleeping_time); 41 42 unsafe { 43 TUSB0216AD_Stop(id); 44 } 45 46 *flag.lock().unwrap() = 1; // 計測終了のフラグを立てる 47 println!("Timer stopped"); 48} 49 50/// CH1, CH2 からのデータを取得する 51pub fn get_data( 52 id: i32, 53 flag: Arc<Mutex<i8>>, 54 _position: &mut Vec<f32>, 55 _intensity: &mut Vec<f32>, 56) { 57 const MAX_LENGTH: usize = 262142; 58 let mut length = MAX_LENGTH as u32; 59 60 println!("Data acquisition started"); 61 loop { 62 if *flag.lock().unwrap() != -1 { 63 break; 64 } 65 thread::sleep(time::Duration::from_millis(10)); 66 } 67 68 let mut data1 = [0; MAX_LENGTH]; 69 let mut data2 = [0; MAX_LENGTH]; 70 let l_ptr = &mut length as *mut u32; 71 72 loop { 73 if *flag.lock().unwrap() == 1 { 74 break; 75 } 76 77 // 問題の部分!!!!!!!!!!!! 78 unsafe { 79 TUSB0216AD_Ad_Data(id, 1, data1.as_mut_ptr(), l_ptr); 80 TUSB0216AD_Ad_Data(id, 2, data2.as_mut_ptr(), l_ptr); 81 } 82 83 84 } 85 println!("Data acquisition stopped"); 86}
lib.rs中の run
を実行すると、
Timer start! Data acquisition started Timer stopped Data acquisition stopped
という文字列が現れることが期待できます。実際、TUSB0216AD_Ad_Data(id, 1, data1.as_mut_ptr(), l_ptr)
とTUSB0216AD_Ad_Data(id, 2, data2.as_mut_ptr(), l_ptr)
の一方のみの時には期待通りの動作をします。しかし上のように2つ並べて書くと、
Timer start!
だけ表示されてプロセスが何のエラーも吐かずに終わってしまいます。
全く自分では原因がわからず困っています。よろしくお願いいたします。
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/08/07 13:12 編集
2021/08/07 13:18