欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

關(guān)于使用rust調(diào)用c++靜態(tài)庫(kù)并編譯nodejs包的問(wèn)題

 更新時(shí)間:2022年08月02日 14:39:03   作者:天邊行云  
這篇文章主要介紹了使用rust調(diào)用c++靜態(tài)庫(kù)并編譯nodejs包的問(wèn)題,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

在項(xiàng)目上經(jīng)常要用到身份證閱讀器、護(hù)照閱讀儀、指紋儀等各種品牌硬件,假如每套系統(tǒng)的都做集成開(kāi)發(fā)那代碼的維護(hù)成本將變得很高,為此采用rust來(lái)調(diào)用廠(chǎng)家提供的sdk c++開(kāi)發(fā)包并封裝成nodejs包,用fastify來(lái)開(kāi)發(fā)成web api獨(dú)立的服務(wù)形式。這樣我們開(kāi)發(fā)系統(tǒng)時(shí)只需調(diào)用web接口即可,跨平臺(tái)又可共用,方便快捷,話(huà)不多說(shuō)來(lái)看代碼如何實(shí)現(xiàn)。

一、創(chuàng)建項(xiàng)目

安裝rust后,打開(kāi)vs新建一個(gè)工程目錄,我們通過(guò)cargo new創(chuàng)建的一個(gè)package項(xiàng)目,加上--lib參數(shù)后創(chuàng)建的項(xiàng)目就是庫(kù)項(xiàng)目(library package)。
cargo new --lib reader
package 就是一個(gè)項(xiàng)目,因此它包含有獨(dú)立的 Cargo.toml 文件,用于項(xiàng)目配置。庫(kù)項(xiàng)目只能作為三方庫(kù)被其它項(xiàng)目引用,而不能獨(dú)立運(yùn)行,即src/lib.rs。
典型的package
如果一個(gè) package 同時(shí)擁有 src/main.rs 和 src/lib.rs,那就意味著它包含兩個(gè)包:庫(kù)包和二進(jìn)制包,這兩個(gè)包名也都是 test_math —— 都與 package 同名。
一個(gè)真實(shí)項(xiàng)目中典型的 package,會(huì)包含多個(gè)二進(jìn)制包,這些包文件被放在 src/bin 目錄下,每一個(gè)文件都是獨(dú)立的二進(jìn)制包,同時(shí)也會(huì)包含一個(gè)庫(kù)包,該包只能存在一個(gè) src/lib.rs:
.
├── Cargo.toml
├── Cargo.lock
├── src
│ ├── main.rs
│ ├── lib.rs
│ └── bin
│ └── main1.rs
│ └── main2.rs
├── tests
│ └── some_integration_tests.rs
├── benches
│ └── simple_bench.rs
└── examples
└── simple_example.rs

唯一庫(kù)包:src/lib.rs
默認(rèn)二進(jìn)制包:src/main.rs,編譯后生成的可執(zhí)行文件與package同名
其余二進(jìn)制包:src/bin/main1.rs 和 src/bin/main2.rs,它們會(huì)分別生成一個(gè)文件同名的二進(jìn)制可執(zhí)行文件
集成測(cè)試文件:tests 目錄下
性能測(cè)試benchmark文件:benches 目錄下
項(xiàng)目示例:examples 目錄下
這種目錄結(jié)構(gòu)基本上是 Rust 的標(biāo)準(zhǔn)目錄結(jié)構(gòu),在 github 的大多數(shù)項(xiàng)目上,你都將看到它的身影。
運(yùn)行Cargo build命令,我們?cè)趖arget\debug目錄下可以看到編譯后的結(jié)果。

二、Cargo.toml

[package]
name = "reader"
version = "0.1.0"
edition = "2018"
exclude = ["reader.node"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
libc = "0.2.9"
libloading = "0.7"
once_cell = "1.8"
serde = { version = "1.0", features = ["derive"] }
widestring = "0.5.1"
serde_json = "1.0"
base64 = "0.13"
hex="0.4.2"
encoding = "0.2"
tokio={version="1.18.0",features = ["full"]}

[dependencies.neon]
version = "0.9"
default-features = false
features = ["napi-5", "channel-api"]

[lib]
crate-type = ["cdylib"]

三、package.json

{
  "name": "reader",
  "version": "0.1.0",
  "description": "",
  "main": "index.node",
  "scripts": {
    "build": "cargo-cp-artifact -nc index.node -- cargo build --message-format=json-render-diagnostics",
    "build-debug": "npm run build --",
    "build-release": "npm run build -- --release",
    "build_win32": "npm run build -- --release --target=i686-pc-windows-msvc",
    "test": "cargo test",
    "run": "cargo run"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "cargo-cp-artifact": "^0.1"
  },
  "dependencies": {
    "express": "^4.17.3"
  }
}

我們可以打印rust看看編譯輸出支持哪些架構(gòu)
rustc --print target-list
//添加 x86編譯鏈接器
rustup target add i686-pc-windows-msvc

四、代碼分析

use std::collections::HashMap;
use std::str;
use std::fmt::Write;
use std::io::{Error};

extern crate encoding;
use encoding::all::GB18030;
use encoding::{DecoderTrap,EncoderTrap,Encoding};

use tokio::time::{sleep, Duration,Instant};
use libc::{c_int, c_void};
use libloading::{Library, Symbol};
use neon::prelude::*;
use once_cell::sync::OnceCell;
use serde::{Deserialize, Serialize};

use widestring::{WideCStr, WideCString, WideChar};
// 編碼轉(zhuǎn)換 utf8 -> utf16le
fn encode(source: &str) -> WideCString {
    let string_source = source.to_string() + "\0";
    WideCString::from_str(&string_source).unwrap()
}
// 解碼轉(zhuǎn)換 utf16le -> utf8
fn decode(source: &[WideChar]) -> String {
    WideCStr::from_slice_truncate(source)
        .unwrap()
        .to_string()
        .unwrap()
}
// 加載 dll
static LIBRARY: OnceCell<Library> = OnceCell::new();

//指定編譯架構(gòu)
static MACHINE_KIND: &str = if cfg!(target_os = "windows") {
    if cfg!(target_arch = "x86") {
        "win32"
    } else if cfg!(target_arch = "x86_x64") {
        "win64"
    } else {
        "other"
    }
} else if cfg!(target_os = "linux") {
    if cfg!(target_arch = "x86") {
        "linux32"
    } else if cfg!(target_arch = "x86_64") {
        "linux64"
    } else if cfg!(target_arch = "aarch64") {
        "aarch64"
    } else if cfg!(target_arch = "arm") {
        "arm"
    } else {
        "other"
    }
} else {
    "other"
};
//定義函數(shù)方法名,這里要根據(jù)c++庫(kù)的函數(shù)名和參數(shù)來(lái)定義,函數(shù)名和參數(shù)類(lèi)型務(wù)必要一致。
type LPCTSTR = *const WideChar;
type BOOL = c_int;
type INITPTR = *const i8;
type CANRST = *mut WideChar;
// 打開(kāi)設(shè)備
type S2V7_open = unsafe extern "system" fn() -> c_int;
// 關(guān)閉設(shè)備
type S2V7_close = unsafe extern "system" fn() -> c_int;
 //【set mode  設(shè)置讀證功能】
type S2V7_set_mode =
    unsafe extern "system" fn(flg_takeColor: c_int, flg_takeUV: c_int, flg_readChipInfo: c_int, flg_readChipFace: c_int) -> c_int; // Type = 0 即可
//【wait Doc. in 等待放卡】
type S2V7_wait_DocIn =
unsafe extern "system" fn(timeout: f64, flg_in: INITPTR) -> c_int; // Type = 0 即可
//【wait Doc. out 等待拿卡】
type S2V7_wait_DocOut =
unsafe extern "system" fn(timeout: f64, flg_out: INITPTR) -> c_int; // Type = 0 即可
 //【process  執(zhí)行讀卡過(guò)程】
type S2V7_process = unsafe extern "system" fn() -> c_int;
 //讀取卡類(lèi)型
type S2V7_get_cardType = unsafe extern "system" fn() -> c_int;
//保存彩照
type S2V7_VIS_saveColor = unsafe extern "system" fn(imgPath: LPCTSTR) -> c_int;
//保存紅外照
type S2V7_VIS_saveIR = unsafe extern "system" fn(imgPath: LPCTSTR) -> c_int;
//【get MRZ text 獲取OCR文字信息】
type S2V7_VIS_getMRZtext = unsafe extern "system" fn(text: LPCTSTR) -> c_int;
//show text information  文字信息
type S2V7_RDO_getBytesByIndex = unsafe extern "system" fn(index: c_int,data: LPCTSTR) -> c_int;
type S2V7_VIS_getBytesByIndex = unsafe extern "system" fn(index: c_int,data: LPCTSTR) -> c_int;
type S2V7_RF_active = unsafe extern "system" fn(antenna: c_int,atr: LPCTSTR, atr_len: c_int) -> c_int;
//構(gòu)建函數(shù)實(shí)例
static V7_OPEN: OnceCell<Symbol<S2V7_open>> = OnceCell::new();
static V7_CLOSE: OnceCell<Symbol<S2V7_close>> = OnceCell::new();
static V7_SET_MODE: OnceCell<Symbol<S2V7_set_mode>> = OnceCell::new();
static V7_WAIT_DOCINT: OnceCell<Symbol<S2V7_wait_DocIn>> = OnceCell::new();
static V7_WAIT_DOCOUT: OnceCell<Symbol<S2V7_wait_DocOut>> = OnceCell::new();
static V7_PROCESS: OnceCell<Symbol<S2V7_process>> = OnceCell::new();
static V7_GET_CARDTYPE: OnceCell<Symbol<S2V7_get_cardType>> = OnceCell::new();
static V7_VIS_SAVECOLOR: OnceCell<Symbol<S2V7_VIS_saveColor>> = OnceCell::new();
static V7_VIS_SAVEIR: OnceCell<Symbol<S2V7_VIS_saveIR>> = OnceCell::new();
static V7_VIS_GETMRZTEXT: OnceCell<Symbol<S2V7_VIS_getMRZtext>> = OnceCell::new();
static V7_RDO_getBytesByIndex: OnceCell<Symbol<S2V7_RDO_getBytesByIndex>> = OnceCell::new();
static V7_VIS_getBytesByIndex: OnceCell<Symbol<S2V7_VIS_getBytesByIndex>> = OnceCell::new();
static V7_RF_active: OnceCell<Symbol<S2V7_RF_active>> = OnceCell::new();
// 對(duì)外導(dǎo)出函數(shù)方法
#[neon::main]
fn main(mut cx: ModuleContext) -> NeonResult<()> {
    cx.export_function("init", init_by_node)?;
    cx.export_function("start", start)?;
}
//加載dll并對(duì)函數(shù)進(jìn)行初始化操作
pub fn init_by_node(mut cx: FunctionContext) -> JsResult<JsNumber> {
	//外部傳進(jìn)來(lái)的參數(shù)(根據(jù)自己的需要來(lái)定義)
    let directory = cx.argument::<JsString>(0)?.value(&mut cx);
    let userid = cx.argument::<JsString>(1)?.value(&mut cx);
    unsafe {
        DIRECTORY_PATH.take();
        DIRECTORY_PATH.set(directory).unwrap();
        USER_ID.take();
        USER_ID.set(userid).unwrap();
    };
    let result = init() as f64;
    Ok(cx.number(result))
}
//核心代碼,加載dll函數(shù)并映射
fn init() -> c_int {
    let directory = unsafe { DIRECTORY_PATH.get().unwrap() };
    let userid = unsafe { USER_ID.get().unwrap() };
    let directory_path = std::path::Path::new(directory).join(MACHINE_KIND);
    if directory_path.exists() {
        let dll_path = directory_path.join(libloading::library_filename("STAR200_V7_DRV"));
        println!("dll_path: {:?}", dll_path);
        if dll_path.exists() {
            match init_dll(dll_path.to_str().unwrap()).is_ok() {
                true => {
                    // 打開(kāi)設(shè)備
                    let init_result = unsafe {V7_OPEN.get_unchecked()()};
                    if init_result == 0 {
                        println!("設(shè)備打開(kāi)成功");
                        return ResultType::Success as c_int;
                    } else {
                        println!("設(shè)備打開(kāi)失敗,代碼:{:?}",init_result);
                        return ResultType::DeviceNotFound as c_int;
                    }
                }
                false => {
                    return ResultType::INITDLLFail as c_int;
                }
            }
        } else {
            return ResultType::DllPathNotExist as c_int;
        }
    } else {
        println!("{:?}", directory_path);
        return ResultType::DirectoryPathNotExist as c_int;
    }
}
// 加載dll
fn init_dll(dll_path: &str) -> Result<bool, Box<dyn std::error::Error>> {
    unsafe {
        if INITDLL {
            return Ok(true);
        }
    }
    println!("加載dll");
    println!("dll_path");
    let library = LIBRARY.get_or_init(|| unsafe { Library::new(dll_path).unwrap() });
    println!("S2V7_open");
    V7_OPEN.get_or_init(|| unsafe { library.get::<S2V7_open>(b"S2V7_open").unwrap() });
    println!("S2V7_close");
    V7_CLOSE.get_or_init(|| unsafe { library.get::<S2V7_close>(b"S2V7_close").unwrap() });
    println!("S2V7_set_mode");
    V7_SET_MODE.get_or_init(|| unsafe {library.get::<S2V7_set_mode>(b"S2V7_set_mode").unwrap()});
    println!("S2V7_wait_DocIn");
    V7_WAIT_DOCINT.get_or_init(|| unsafe { library.get::<S2V7_wait_DocIn>(b"S2V7_wait_DocIn").unwrap() });
    println!("S2V7_wait_DocOut");
    V7_WAIT_DOCOUT.get_or_init(|| unsafe { library.get::<S2V7_wait_DocOut>(b"S2V7_wait_DocOut").unwrap() });
    V7_PROCESS.get_or_init(|| unsafe { library.get::<S2V7_process>(b"S2V7_process").unwrap() });
    V7_GET_CARDTYPE.get_or_init(|| unsafe { library.get::<S2V7_get_cardType>(b"S2V7_get_cardType").unwrap() });
    V7_VIS_SAVECOLOR.get_or_init(|| unsafe { library.get::<S2V7_VIS_saveColor>(b"S2V7_VIS_saveColor").unwrap() });
    V7_VIS_SAVEIR.get_or_init(|| unsafe { library.get::<S2V7_VIS_saveIR>(b"S2V7_VIS_saveIR").unwrap() });
    V7_VIS_GETMRZTEXT.get_or_init(|| unsafe { library.get::<S2V7_VIS_getMRZtext>(b"S2V7_VIS_getMRZtext").unwrap() });
    V7_RDO_getBytesByIndex.get_or_init(|| unsafe { library.get::<S2V7_RDO_getBytesByIndex>(b"S2V7_RDO_getBytesByIndex").unwrap() });
    V7_VIS_getBytesByIndex.get_or_init(|| unsafe { library.get::<S2V7_VIS_getBytesByIndex>(b"S2V7_VIS_getBytesByIndex").unwrap() });
    V7_RF_active.get_or_init(|| unsafe { library.get::<S2V7_RF_active>(b"S2V7_RF_active").unwrap() });
    unsafe {
        INITDLL = true;
    }
    Ok(true)
}
//創(chuàng)建新線(xiàn)程來(lái)監(jiān)測(cè)設(shè)備讀證操作
fn start(mut cx: FunctionContext) -> JsResult<JsUndefined> {
    let callback = cx.argument::<JsFunction>(0)?.root(&mut cx);
    let mut channel = cx.channel();
    channel.reference(&mut cx);
    println!("start {}", channel.has_ref());
    let index = unsafe {
        DEVICE_START_INDEX += 1;
        DEVICE_START_INDEX
    };
    std::thread::spawn(move || {
        // Do the heavy lifting inside the background thread.
        device_start(callback, channel, index);
    });
    Ok(cx.undefined())
}
use std::sync::{Arc, Mutex};
fn device_start(callback: Root<JsFunction>, channel: Channel, index: u64) {
    let index = index;
    let callback = Arc::new(Mutex::new(callback));
    //設(shè)置讀證功能
    unsafe { V7_SET_MODE.get_unchecked()(1,1,1,1) };
    loop {
        if index != unsafe { DEVICE_START_INDEX } {
            break;
        };
        let callback_clone = Arc::clone(&callback);
        let mut result = RecogIDCardEXResult::default();
        let mut flg_in:i8=0;
        match unsafe { V7_WAIT_DOCINT.get_unchecked()(5.0,&mut flg_in) } {
            // 設(shè)備正常 檢測(cè)是否有放入證件
            0 => {
                if flg_in==0{
                    //檢查是否放入超時(shí)
                    result.record_type = ResultType::CheckCardNotInOrOut as i32;
                    break;
                }
                result.device_online = true;
                result.device_name =unsafe { DEVCIE_NAME.get_or_init(|| "".to_string()).to_string() };
                
                match unsafe { V7_PROCESS.get_unchecked()() } {
                    // 證件有放入
                    0 => {
                        result.record_type = ResultType::CheckCardInput as i32;
                    }
                    // 未檢測(cè)到OCR區(qū)域
                    -1 => {
                        result.record_type = ResultType::OCRFail as i32;
                    }
                    // 設(shè)備離線(xiàn)
                    -3 => {
                        result.device_online = false;
                        result.record_type = init();
                    }
                    _ => {
                        result.record_type = ResultType::Unknown as i32;
                    }
                }
            }
            -3 => {
                //設(shè)備離線(xiàn)
                let init = init();
                result.device_online = false;
                result.record_type = init;
            }
            _ => {
                //未知錯(cuò)誤
                result.record_type = ResultType::Unknown as i32;
            }
        };
        if unsafe { *NEED_RECORD.get_or_init(|| false) } {
            println!("手工點(diǎn)擊識(shí)別+1");
            result.record_type = ResultType::CheckCardInput as i32;
        } 
        // let time_now = std::time::Instant::now();
        if result.record_type == ResultType::CheckCardInput as i32 {
            let _result = recog_card();
            result.success = _result.success;
            result.img_base64 = _result.img_base64;
            result.reg_info = _result.reg_info;
            result.card_type = _result.card_type;
            result.card_name = _result.card_name;
        }
        let neet_sendinfo = if Some(true) == unsafe { NEED_RECORD.take() } {
            true
        } else {
            false
        };
        // let elapsed = time_now.elapsed();
        // println!("識(shí)別時(shí)間結(jié)束時(shí)間 {:.6?}", elapsed);
        if result.record_type != ResultType::CheckCardNotInOrOut as i32
            && (*unsafe { RESULT_TYPE.get_or_init(|| -10000) } != result.record_type
                || result.record_type == ResultType::CheckCardInput as i32
                || neet_sendinfo)
        {
            unsafe {
                RESULT_TYPE.take();
                RESULT_TYPE.set(result.record_type).unwrap();
            }
            channel.send(move |mut cx| {
                let result_json = serde_json::to_string(&result).unwrap();
                let callback = callback_clone.lock().unwrap().to_inner(&mut cx);
                let this = cx.undefined();
                let args = vec![cx.string(&result_json)];
                callback.call(&mut cx, this, args)?;
                Ok(())
            });
        }
        std::thread::sleep(std::time::Duration::from_millis(20));
    }
}

完整源碼

use std::collections::HashMap;
use libc::{c_int, c_void};
use libloading::{Library, Symbol};
use neon::prelude::*;
use once_cell::sync::OnceCell;
use serde::Serialize;
extern crate encoding;
use encoding::all::GB18030;
use encoding::{DecoderTrap,EncoderTrap,Encoding};
use widestring::{WideCStr, WideCString, WideChar};
// 編碼轉(zhuǎn)換 utf8 -> utf16le
fn encode(source: &str) -> WideCString {
    let string_source = source.to_string() + "\0";
    WideCString::from_str(&string_source).unwrap()
}
// 解碼轉(zhuǎn)換 utf16le -> utf8
fn decode(source: &[WideChar]) -> String {
    WideCStr::from_slice_truncate(source)
        .unwrap()
        .to_string()
        .unwrap()
}
// 加載 dll
static LIBRARY: OnceCell<Library> = OnceCell::new();
static MACHINE_KIND: &str = if cfg!(target_os = "windows") {
    if cfg!(target_arch = "x86") {
        "win32"
    } else if cfg!(target_arch = "x86_x64") {
        "win64"
    } else {
        "other"
    }
} else if cfg!(target_os = "linux") {
    if cfg!(target_arch = "x86") {
        "linux32"
    } else if cfg!(target_arch = "x86_64") {
        "linux64"
    } else if cfg!(target_arch = "aarch64") {
        "aarch64"
    } else if cfg!(target_arch = "arm") {
        "arm"
    } else {
        "other"
    }
} else {
    "other"
};
//設(shè)置識(shí)別的證件 ID
// 設(shè)置當(dāng)前要識(shí)別的證件類(lèi)型,并將
// 之前已經(jīng)設(shè)置的證件類(lèi)型清除。
// nMainID 主要識(shí)別類(lèi)型,nSubID 子類(lèi)型
//  nSubID 頭指針,默認(rèn)將數(shù)組
// nSubID 第 一 個(gè) 元 素 賦 值 為 0 即
// nSubID[0]=0
// type S = c_int[];
type LPCTSTR = *const WideChar;
type BOOL = c_int;
type INITPTR = *const i8;
type CANRST = *mut WideChar;
// 打開(kāi)設(shè)備
type S2V7_open = unsafe extern "system" fn() -> c_int;
// 關(guān)閉設(shè)備
type S2V7_close = unsafe extern "system" fn() -> c_int;
 //【set mode  設(shè)置讀證功能】
type S2V7_set_mode =
    unsafe extern "system" fn(flg_takeColor: c_int, flg_takeUV: c_int, flg_readChipInfo: c_int, flg_readChipFace: c_int) -> c_int; // Type = 0 即可
//【wait Doc. in 等待放卡】
type S2V7_wait_DocIn =
unsafe extern "system" fn(timeout: f64, flg_in: INITPTR) -> c_int; // Type = 0 即可
//【wait Doc. out 等待拿卡】
type S2V7_wait_DocOut =
unsafe extern "system" fn(timeout: f64, flg_out: INITPTR) -> c_int; // Type = 0 即可
 //【process  執(zhí)行讀卡過(guò)程】
type S2V7_process = unsafe extern "system" fn() -> c_int;
 //讀取卡類(lèi)型
type S2V7_get_cardType = unsafe extern "system" fn() -> c_int;
//保存彩照
type S2V7_VIS_saveColor = unsafe extern "system" fn(imgPath: LPCTSTR) -> c_int;
//保存紅外照
type S2V7_VIS_saveIR = unsafe extern "system" fn(imgPath: LPCTSTR) -> c_int;
//【get MRZ text 獲取OCR文字信息】
type S2V7_VIS_getMRZtext = unsafe extern "system" fn(text: LPCTSTR) -> c_int;
//show text information  文字信息
type S2V7_RDO_getBytesByIndex = unsafe extern "system" fn(index: c_int,data: LPCTSTR) -> c_int;
type S2V7_VIS_getBytesByIndex = unsafe extern "system" fn(index: c_int,data: LPCTSTR) -> c_int;
type S2V7_RF_active = unsafe extern "system" fn(antenna: c_int,atr: LPCTSTR, atr_len: c_int) -> c_int;
static V7_OPEN: OnceCell<Symbol<S2V7_open>> = OnceCell::new();
static V7_CLOSE: OnceCell<Symbol<S2V7_close>> = OnceCell::new();
static V7_SET_MODE: OnceCell<Symbol<S2V7_set_mode>> = OnceCell::new();
static V7_WAIT_DOCINT: OnceCell<Symbol<S2V7_wait_DocIn>> = OnceCell::new();
static V7_WAIT_DOCOUT: OnceCell<Symbol<S2V7_wait_DocOut>> = OnceCell::new();
static V7_PROCESS: OnceCell<Symbol<S2V7_process>> = OnceCell::new();
static V7_GET_CARDTYPE: OnceCell<Symbol<S2V7_get_cardType>> = OnceCell::new();
static V7_VIS_SAVECOLOR: OnceCell<Symbol<S2V7_VIS_saveColor>> = OnceCell::new();
static V7_VIS_SAVEIR: OnceCell<Symbol<S2V7_VIS_saveIR>> = OnceCell::new();
static V7_VIS_GETMRZTEXT: OnceCell<Symbol<S2V7_VIS_getMRZtext>> = OnceCell::new();
static V7_RDO_getBytesByIndex: OnceCell<Symbol<S2V7_RDO_getBytesByIndex>> = OnceCell::new();
static V7_VIS_getBytesByIndex: OnceCell<Symbol<S2V7_VIS_getBytesByIndex>> = OnceCell::new();
static V7_RF_active: OnceCell<Symbol<S2V7_RF_active>> = OnceCell::new();
// static
static mut INITDLL: bool = false;
static mut DEVICE_START_INDEX: u64 = 0;
static mut DIRECTORY_PATH: OnceCell<String> = OnceCell::new();
static mut USER_ID: OnceCell<String> = OnceCell::new();
static mut DEVCIE_NAME: OnceCell<String> = OnceCell::new();
static mut RESULT_TYPE: OnceCell<i32> = OnceCell::new();
static mut NEED_RECORD: OnceCell<bool> = OnceCell::new();
// 初始化dll
fn init_dll(dll_path: &str) -> Result<bool, Box<dyn std::error::Error>> {
    unsafe {
        if INITDLL {
            return Ok(true);
        }
    }
    println!("加載dll");
    println!("dll_path");
    let library = LIBRARY.get_or_init(|| unsafe { Library::new(dll_path).unwrap() });
    println!("S2V7_open");
    V7_OPEN.get_or_init(|| unsafe { library.get::<S2V7_open>(b"S2V7_open").unwrap() });
    println!("S2V7_close");
    V7_CLOSE.get_or_init(|| unsafe { library.get::<S2V7_close>(b"S2V7_close").unwrap() });
    println!("S2V7_set_mode");
    V7_SET_MODE.get_or_init(|| unsafe {library.get::<S2V7_set_mode>(b"S2V7_set_mode").unwrap()});
    println!("S2V7_wait_DocIn");
    V7_WAIT_DOCINT.get_or_init(|| unsafe { library.get::<S2V7_wait_DocIn>(b"S2V7_wait_DocIn").unwrap() });
    println!("S2V7_wait_DocOut");
    V7_WAIT_DOCOUT.get_or_init(|| unsafe { library.get::<S2V7_wait_DocOut>(b"S2V7_wait_DocOut").unwrap() });
    V7_PROCESS.get_or_init(|| unsafe { library.get::<S2V7_process>(b"S2V7_process").unwrap() });
    V7_GET_CARDTYPE.get_or_init(|| unsafe { library.get::<S2V7_get_cardType>(b"S2V7_get_cardType").unwrap() });
    V7_VIS_SAVECOLOR.get_or_init(|| unsafe { library.get::<S2V7_VIS_saveColor>(b"S2V7_VIS_saveColor").unwrap() });
    V7_VIS_SAVEIR.get_or_init(|| unsafe { library.get::<S2V7_VIS_saveIR>(b"S2V7_VIS_saveIR").unwrap() });
    V7_VIS_GETMRZTEXT.get_or_init(|| unsafe { library.get::<S2V7_VIS_getMRZtext>(b"S2V7_VIS_getMRZtext").unwrap() });
    V7_RDO_getBytesByIndex.get_or_init(|| unsafe { library.get::<S2V7_RDO_getBytesByIndex>(b"S2V7_RDO_getBytesByIndex").unwrap() });
    V7_VIS_getBytesByIndex.get_or_init(|| unsafe { library.get::<S2V7_VIS_getBytesByIndex>(b"S2V7_VIS_getBytesByIndex").unwrap() });
    V7_RF_active.get_or_init(|| unsafe { library.get::<S2V7_RF_active>(b"S2V7_RF_active").unwrap() });
    unsafe {
        INITDLL = true;
    }
    Ok(true)
}
fn init() -> c_int {
    let directory = unsafe { DIRECTORY_PATH.get().unwrap() };
    let userid = unsafe { USER_ID.get().unwrap() };
    let directory_path = std::path::Path::new(directory).join(MACHINE_KIND);
    if directory_path.exists() {
        let dll_path = directory_path.join(libloading::library_filename("STAR200_V7_DRV"));
        println!("dll_path: {:?}", dll_path);
        if dll_path.exists() {
            match init_dll(dll_path.to_str().unwrap()).is_ok() {
                true => {
                    // 打開(kāi)設(shè)備
                    let init_result = unsafe {V7_OPEN.get_unchecked()()};
                    if init_result == 0 {
                        println!("設(shè)備打開(kāi)成功");
                        return ResultType::Success as c_int;
                    } else {
                        println!("設(shè)備打開(kāi)失敗,代碼:{:?}",init_result);
                        return ResultType::DeviceNotFound as c_int;
                    }
                }
                false => {
                    return ResultType::INITDLLFail as c_int;
                }
            }
        } else {
            return ResultType::DllPathNotExist as c_int;
        }
    } else {
        println!("{:?}", directory_path);
        return ResultType::DirectoryPathNotExist as c_int;
    }
}
pub fn init_by_node(mut cx: FunctionContext) -> JsResult<JsNumber> {
    let directory = cx.argument::<JsString>(0)?.value(&mut cx);
    let userid = cx.argument::<JsString>(1)?.value(&mut cx);
    unsafe {
        DIRECTORY_PATH.take();
        DIRECTORY_PATH.set(directory).unwrap();
        USER_ID.take();
        USER_ID.set(userid).unwrap();
    };
    let result = init() as f64;
    Ok(cx.number(result))
}
#[allow(dead_code)] // 允許dead_code
enum ResultType {
    DirectoryPathNotExist = -2003, // 找不到運(yùn)行目錄
    DllPathNotExist = -2001,       // 找不到dll文件
    INITDLLFail = -2000,           // 初始化dll
    Success = 0,                   // 成功
    UserIdFail = 2001,             //用戶(hù) ID 錯(cuò)誤
    DeviceInitFail = 2002,         //  設(shè)備初始化失敗
    DeviceKernelInitFail = 2003,   // 初始化核心失敗
    DeviceDatInitFail = 2004,      //未找到授權(quán)文件
    DeviceNotInit = 2101,          // 設(shè)備未初始化
    DeviceNotFound = 2102,         // 沒(méi)有找到設(shè)備
    DeviceReConnect = 2103,        // 重新連接設(shè)備
    Unknown = -100,                // 未知錯(cuò)誤
    CheckCardInput = 3001,         // 證件放入設(shè)備
    CheckCardOut = 3002,           // 證件移出設(shè)備
    CheckCardNotInOrOut = 3000,    // 證件無(wú)放入或拿出
    CheckCardBarCode = 3003,       // 檢測(cè)到手機(jī)條碼
    OCRFail=-1,                    // 未檢測(cè)到OCR區(qū)域
}
type RecogIDCardEXResultItem = HashMap<i32, [String; 2]>;
#[derive(Default, Serialize)]
pub struct RecogIDCardEXResultObject {
    pub viz_result: RecogIDCardEXResultItem,
    pub viz_orc_result: RecogIDCardEXResultItem,
    pub mrz_result: RecogIDCardEXResultItem,
    pub mrz_ocr_result: RecogIDCardEXResultItem,
    pub chip_result: RecogIDCardEXResultItem,
}
#[derive(Default, Serialize)]
pub struct RecogIDCardEXResult {
    pub device_name: String,
    pub device_online: bool,
    pub reg_info: RecogIDCardEXResultObject,
    pub img_base64: HashMap<String, String>,
    pub card_type: i32,
    pub record_type: i32,
    pub card_name: String,
    pub success: bool, // 識(shí)別是否成功
}
static SAVE_IMAGE_REUSLT_NAME: [&str; 5] = [
    "tempHeadEC.jpg",
    "tempHead.jpg",
    "tempUV.jpg",
    "tempIR.jpg",
    "temp.jpg",
];
fn start(mut cx: FunctionContext) -> JsResult<JsUndefined> {
    let callback = cx.argument::<JsFunction>(0)?.root(&mut cx);
    let mut channel = cx.channel();
    channel.reference(&mut cx);
    println!("start {}", channel.has_ref());
    let index = unsafe {
        DEVICE_START_INDEX += 1;
        DEVICE_START_INDEX
    };
    std::thread::spawn(move || {
        // Do the heavy lifting inside the background thread.
        device_start(callback, channel, index);
    });
    Ok(cx.undefined())
}
use std::sync::{Arc, Mutex};
fn device_start(callback: Root<JsFunction>, channel: Channel, index: u64) {
    let index = index;
    let callback = Arc::new(Mutex::new(callback));
    //設(shè)置讀證功能
    unsafe { V7_SET_MODE.get_unchecked()(1,1,1,1) };
    loop {
        if index != unsafe { DEVICE_START_INDEX } {
            break;
        };
        let callback_clone = Arc::clone(&callback);
        let mut result = RecogIDCardEXResult::default();
        let mut flg_in:i8=0;
        match unsafe { V7_WAIT_DOCINT.get_unchecked()(5.0,&mut flg_in) } {
            // 設(shè)備正常 檢測(cè)是否有放入證件
            0 => {
                if flg_in==0{
                    //檢查是否放入超時(shí)
                    result.record_type = ResultType::CheckCardNotInOrOut as i32;
                    break;
                }
                result.device_online = true;
                result.device_name =unsafe { DEVCIE_NAME.get_or_init(|| "".to_string()).to_string() };
                
                match unsafe { V7_PROCESS.get_unchecked()() } {
                    // 證件有放入
                    0 => {
                        result.record_type = ResultType::CheckCardInput as i32;
                    }
                    // 未檢測(cè)到OCR區(qū)域
                    -1 => {
                        result.record_type = ResultType::OCRFail as i32;
                    }
                    // 未找到非接卡
                    // v if v/10 == -21 => {
                    //     result.record_type = ResultType::OCRFail as i32;
                    // }
                    // 設(shè)備離線(xiàn)
                    -3 => {
                        result.device_online = false;
                        result.record_type = init();
                    }
                    _ => {
                        result.record_type = ResultType::Unknown as i32;
                    }
                }
            }
            -3 => {
                //設(shè)備離線(xiàn)
                let init = init();
                result.device_online = false;
                result.record_type = init;
            }
            _ => {
                //未知錯(cuò)誤
                result.record_type = ResultType::Unknown as i32;
            }
        };
        if unsafe { *NEED_RECORD.get_or_init(|| false) } {
            println!("手工點(diǎn)擊識(shí)別+1");
            result.record_type = ResultType::CheckCardInput as i32;
        } 
        // let time_now = std::time::Instant::now();
        if result.record_type == ResultType::CheckCardInput as i32 {
            let _result = recog_card();
            result.success = _result.success;
            result.img_base64 = _result.img_base64;
            result.reg_info = _result.reg_info;
            result.card_type = _result.card_type;
            result.card_name = _result.card_name;
        }
        let neet_sendinfo = if Some(true) == unsafe { NEED_RECORD.take() } {
            true
        } else {
            false
        };
        // let elapsed = time_now.elapsed();
        // println!("識(shí)別時(shí)間結(jié)束時(shí)間 {:.6?}", elapsed);
        if result.record_type != ResultType::CheckCardNotInOrOut as i32
            && (*unsafe { RESULT_TYPE.get_or_init(|| -10000) } != result.record_type
                || result.record_type == ResultType::CheckCardInput as i32
                || neet_sendinfo)
        {
            unsafe {
                RESULT_TYPE.take();
                RESULT_TYPE.set(result.record_type).unwrap();
            }
            channel.send(move |mut cx| {
                let result_json = serde_json::to_string(&result).unwrap();
                let callback = callback_clone.lock().unwrap().to_inner(&mut cx);
                let this = cx.undefined();
                let args = vec![cx.string(&result_json)];
                callback.call(&mut cx, this, args)?;
                Ok(())
            });
        }
        std::thread::sleep(std::time::Duration::from_millis(20));
    }
}
// 白光圖、紅外
// 圖、紫外圖、版面頭像和芯片頭像
pub fn recog_card() -> RecogIDCardEXResult {
    let time_now = std::time::Instant::now();
    let mut result = RecogIDCardEXResult::default();
    result.device_online = true;
    let img_path_directory = std::path::Path::new(unsafe { DIRECTORY_PATH.get().unwrap() });
    let ir_img_path = img_path_directory.join("ir.jpg");
    let color_img_path = img_path_directory.join("color.jpg");
    //顯示紅外照
    let irResult = unsafe {V7_VIS_SAVEIR.get_unchecked()(encode(ir_img_path.to_str().unwrap()).as_ptr() as LPCTSTR)};
    //顯示彩照
    let colorResult = unsafe {V7_VIS_SAVECOLOR.get_unchecked()(encode(color_img_path.to_str().unwrap()).as_ptr() as LPCTSTR)};
    if irResult==0{
        if ir_img_path.exists() {
            match std::fs::read(&ir_img_path) {
                Ok(image_data) => {
                    println!("讀取照片成功");
                    let image_data = base64::encode(&image_data);
                    let base64_string = String::from("data:image/jpg;base64,");
                    std::fs::remove_file(ir_img_path).unwrap();
                    result.img_base64.insert("0".to_string(), base64_string + &image_data);
                }
                Err(e) => {
                    println!("讀取照片拋異常");
                    println!(
                        "{:?} {:?}",
                        e,
                        "ir.jpg",
                    );
                }
            };
        }
    }
    if colorResult==0{
        if color_img_path.exists() {
            match std::fs::read(&color_img_path) {
                Ok(image_data) => {
                    println!("讀取照片成功");
                    let image_data = base64::encode(&image_data);
                    let base64_string = String::from("data:image/jpg;base64,");
                    std::fs::remove_file(color_img_path).unwrap();
                    result.img_base64.insert("1".to_string(), base64_string + &image_data);
                }
                Err(e) => {
                    println!("讀取照片拋異常");
                    println!(
                        "{:?} {:?}",
                        e,
                        "color.jpg",
                    );
                }
            };
        }
    }
    let mut ocritem = RecogIDCardEXResultObject::default();
    let mut index: c_int = 0;
    //orc識(shí)別文字
    let mut mrztext = [0; 1024];
    let x = unsafe {V7_VIS_GETMRZTEXT.get_unchecked()(mrztext.as_mut_ptr())};
    if x==0{
        let result_item = ["MRZ".to_string(), decode(&mrztext)];
        ocritem.mrz_result.insert(index, result_item);
        index+=1;
    }
    let mut data:[u16; 256] = [0; 256];
    let mut len = unsafe {V7_RDO_getBytesByIndex.get_unchecked()(0,data.as_mut_ptr())};
    if len>0{
        ocritem.mrz_result.insert(index, ["編號(hào)".to_string(), decode(&data)]);
        index+=1;
        len = unsafe {V7_RDO_getBytesByIndex.get_unchecked()(1,data.as_mut_ptr())};
        ocritem.mrz_result.insert(index, ["國(guó)籍".to_string(), decode(&data)]);
        index+=1;
        len = unsafe {V7_RDO_getBytesByIndex.get_unchecked()(2,data.as_mut_ptr())};
        ocritem.mrz_result.insert(index, ["民族".to_string(), decode(&data)]);
        index+=1;
        len = unsafe {V7_RDO_getBytesByIndex.get_unchecked()(3,data.as_mut_ptr())};
        ocritem.mrz_result.insert(index, ["姓名".to_string(), decode(&data)]);
        index+=1;
        len = unsafe {V7_RDO_getBytesByIndex.get_unchecked()(4,data.as_mut_ptr())};
        let cardType= unsafe {V7_GET_CARDTYPE.get_unchecked()()};
        if cardType==101{
            //身份證是UTF8格式
            ocritem.mrz_result.insert(index, ["中文名".to_string(), decode(&data)]);
        }else{
            ocritem.mrz_result.insert(index, ["中文名".to_string(), decode(&data)]);
            // //中國(guó)護(hù)照的中文姓名 是GBK編碼的
            // let name=GB18030.decode(&data, DecoderTrap::Strict).unwrap();
            // ocritem.mrz_result.insert(index, ["中文名".to_string(), name.replace("\u{0}","")]);
        }
        index+=1;
        len = unsafe {V7_RDO_getBytesByIndex.get_unchecked()(5,data.as_mut_ptr())};
        ocritem.mrz_result.insert(index, ["性別".to_string(), decode(&data)]);
        index+=1;
        len = unsafe {V7_RDO_getBytesByIndex.get_unchecked()(6,data.as_mut_ptr())};
        ocritem.mrz_result.insert(index, ["出生日期".to_string(), decode(&data)]);
        index+=1;
        len = unsafe {V7_RDO_getBytesByIndex.get_unchecked()(7,data.as_mut_ptr())};
        ocritem.mrz_result.insert(index, ["地址".to_string(), decode(&data)]);
        index+=1;
        len = unsafe {V7_RDO_getBytesByIndex.get_unchecked()(8,data.as_mut_ptr())};
        ocritem.mrz_result.insert(index, ["簽發(fā)機(jī)關(guān)".to_string(), decode(&data)]);
        index+=1;
        len = unsafe {V7_RDO_getBytesByIndex.get_unchecked()(9,data.as_mut_ptr())};
        ocritem.mrz_result.insert(index, ["有效期始".to_string(), decode(&data)]);
        index+=1;
        len = unsafe {V7_RDO_getBytesByIndex.get_unchecked()(10,data.as_mut_ptr())};
        ocritem.mrz_result.insert(index, ["有效期止".to_string(), decode(&data)]);
        index+=1;
        len = unsafe {V7_RDO_getBytesByIndex.get_unchecked()(20,data.as_mut_ptr())};
        ocritem.mrz_result.insert(index, ["港澳臺(tái)ID".to_string(), decode(&data)]);
        index+=1;
    }
    else{
        len = unsafe {V7_VIS_getBytesByIndex.get_unchecked()(0,data.as_mut_ptr())};
        ocritem.mrz_result.insert(index, ["編號(hào)".to_string(), decode(&data)]);
        index+=1;
        len = unsafe {V7_VIS_getBytesByIndex.get_unchecked()(1,data.as_mut_ptr())};
        ocritem.mrz_result.insert(index, ["國(guó)籍".to_string(), decode(&data)]);
        index+=1;
        len = unsafe {V7_VIS_getBytesByIndex.get_unchecked()(2,data.as_mut_ptr())};
        ocritem.mrz_result.insert(index, ["民族".to_string(), decode(&data)]);
        index+=1;
        len = unsafe {V7_VIS_getBytesByIndex.get_unchecked()(3,data.as_mut_ptr())};
        ocritem.mrz_result.insert(index, ["姓名".to_string(), decode(&data)]);
        index+=1;
       
        //中國(guó)護(hù)照的中文姓名 是GBK編碼的, 身份證不會(huì)執(zhí)行到這里
        len = unsafe {V7_VIS_getBytesByIndex.get_unchecked()(4,data.as_mut_ptr())};
        ocritem.mrz_result.insert(index, ["中文名".to_string(), decode(&data)]);
        // let name=GB18030.decode(&data, DecoderTrap::Strict).unwrap();
        // ocritem.mrz_result.insert(index, ["中文名".to_string(), name.replace("\u{0}","")]);
        index+=1;
        len = unsafe {V7_VIS_getBytesByIndex.get_unchecked()(5,data.as_mut_ptr())};
        ocritem.mrz_result.insert(index, ["性別".to_string(), decode(&data)]);
        index+=1;
        len = unsafe {V7_VIS_getBytesByIndex.get_unchecked()(6,data.as_mut_ptr())};
        ocritem.mrz_result.insert(index, ["出生日期".to_string(), decode(&data)]);
        index+=1;
        len = unsafe {V7_VIS_getBytesByIndex.get_unchecked()(7,data.as_mut_ptr())};
        ocritem.mrz_result.insert(index, ["地址".to_string(), decode(&data)]);
        index+=1;
        len = unsafe {V7_VIS_getBytesByIndex.get_unchecked()(8,data.as_mut_ptr())};
        ocritem.mrz_result.insert(index, ["簽發(fā)機(jī)關(guān)".to_string(), decode(&data)]);
        index+=1;
        len = unsafe {V7_VIS_getBytesByIndex.get_unchecked()(9,data.as_mut_ptr())};
        ocritem.mrz_result.insert(index, ["有效期始".to_string(), decode(&data)]);
        index+=1;
        len = unsafe {V7_VIS_getBytesByIndex.get_unchecked()(10,data.as_mut_ptr())};
        ocritem.mrz_result.insert(index, ["有效期止".to_string(), decode(&data)]);
        index+=1;
        len = unsafe {V7_VIS_getBytesByIndex.get_unchecked()(20,data.as_mut_ptr())};
        ocritem.mrz_result.insert(index, ["港澳臺(tái)ID".to_string(), decode(&data)]);
        index+=1;
    }
   
    result.reg_info=ocritem;
    result.success = true;
    result.card_type = unsafe {V7_GET_CARDTYPE.get_unchecked()()};
    let elapsed = time_now.elapsed();
    println!("{:.6?}", elapsed);
    return result;
}
pub fn regcord_by_node(mut cx: FunctionContext) -> JsResult<JsNull> {
    println!("regcord_by_node");
    unsafe {
        NEED_RECORD.take();
        NEED_RECORD.set(true).unwrap();
    };
    Ok(cx.null())
}
#[neon::main]
fn main(mut cx: ModuleContext) -> NeonResult<()> {
    cx.export_function("init", init_by_node)?;
    cx.export_function("start", start)?;
    cx.export_function("regcord_by_node", regcord_by_node)?;
    Ok(())
}

到此這篇關(guān)于使用rust調(diào)用c++靜態(tài)庫(kù)并編譯nodejs包的文章就介紹到這了,更多相關(guān)rust調(diào)用c++靜態(tài)庫(kù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 利用rust編一個(gè)靜態(tài)博客工具

    利用rust編一個(gè)靜態(tài)博客工具

    這篇文章主要為大家詳細(xì)介紹了如何利用rust編一個(gè)靜態(tài)博客工具,這個(gè)靜態(tài)博客的工具主要是把md文檔轉(zhuǎn)為html靜態(tài)網(wǎng)站/博客,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-12-12
  • 探索Rust切片與Go有何區(qū)別

    探索Rust切片與Go有何區(qū)別

    這篇文章主要為大家介紹了Rust切片與Go的區(qū)別探索,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • 詳解Rust編程中的共享狀態(tài)并發(fā)執(zhí)行

    詳解Rust編程中的共享狀態(tài)并發(fā)執(zhí)行

    雖然消息傳遞是一個(gè)很好的處理并發(fā)的方式,但并不是唯一一個(gè),另一種方式是讓多個(gè)線(xiàn)程擁有相同的共享數(shù)據(jù),本文給大家介紹Rust編程中的共享狀態(tài)并發(fā)執(zhí)行,感興趣的朋友一起看看吧
    2023-11-11
  • Rust如何進(jìn)行模塊化開(kāi)發(fā)技巧分享

    Rust如何進(jìn)行模塊化開(kāi)發(fā)技巧分享

    Rust模塊化,模塊化有助于代碼的管理和層次邏輯的清晰,本文主要介紹了Rust如何進(jìn)行模塊化開(kāi)發(fā),結(jié)合實(shí)例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • 關(guān)于Rust?使用?dotenv?來(lái)設(shè)置環(huán)境變量的問(wèn)題

    關(guān)于Rust?使用?dotenv?來(lái)設(shè)置環(huán)境變量的問(wèn)題

    在項(xiàng)目中,我們通常需要設(shè)置一些環(huán)境變量,用來(lái)保存一些憑證或其它數(shù)據(jù),這時(shí)我們可以使用dotenv這個(gè)crate,接下來(lái)通過(guò)本文給大家介紹Rust?使用dotenv來(lái)設(shè)置環(huán)境變量的問(wèn)題,感興趣的朋友一起看看吧
    2022-01-01
  • Rust-使用dotenvy加載和使用環(huán)境變量的過(guò)程詳解

    Rust-使用dotenvy加載和使用環(huán)境變量的過(guò)程詳解

    系統(tǒng)的開(kāi)發(fā),測(cè)試和部署離不開(kāi)環(huán)境變量,今天分享在Rust的系統(tǒng)開(kāi)發(fā)中,使用dotenvy來(lái)讀取和使用環(huán)境變量,感興趣的朋友跟隨小編一起看看吧
    2023-11-11
  • Rust中類(lèi)型轉(zhuǎn)換在錯(cuò)誤處理中的應(yīng)用小結(jié)

    Rust中類(lèi)型轉(zhuǎn)換在錯(cuò)誤處理中的應(yīng)用小結(jié)

    隨著項(xiàng)目的進(jìn)展,關(guān)于Rust的故事又翻開(kāi)了新的一頁(yè),今天來(lái)到了服務(wù)器端的開(kāi)發(fā)場(chǎng)景,發(fā)現(xiàn)錯(cuò)誤處理中的錯(cuò)誤類(lèi)型轉(zhuǎn)換有必要分享一下,對(duì)Rust錯(cuò)誤處理相關(guān)知識(shí)感興趣的朋友一起看看吧
    2023-09-09
  • 解析Rust?struct?中的生命周期

    解析Rust?struct?中的生命周期

    rust?的生命周期保證了內(nèi)存的安全性,同時(shí)也增加了開(kāi)發(fā)者的心智負(fù)擔(dān)。是在上線(xiàn)之前多費(fèi)心思寫(xiě)代碼,還是在上線(xiàn)以后忙忙活活查問(wèn)題,這是個(gè)?trade?off?問(wèn)題,這篇文章主要介紹了Rust?struct?中的生命周期,需要的朋友可以參考下
    2022-10-10
  • 詳解Rust中泛型的使用

    詳解Rust中泛型的使用

    泛型是一種在編寫(xiě)代碼時(shí)不指定具體類(lèi)型,而在使用時(shí)再確定類(lèi)型的編程技巧,本文將詳細(xì)介紹?Rust?中泛型的相關(guān)概念和用法,希望對(duì)大家有所幫助
    2023-06-06
  • MacBook Pro安裝rust編程環(huán)境的過(guò)程

    MacBook Pro安裝rust編程環(huán)境的過(guò)程

    rustup是一個(gè)用于管理Rust版本和工具鏈的工具,這篇文章主要介紹了MacBook Pro安裝rust編程環(huán)境的過(guò)程,感興趣的朋友跟隨小編一起看看吧
    2024-02-02

最新評(píng)論