Rust: Bindgen绑定CTP C++原生接口尝试

一、 环境准备:

WSL2 +Bindgen + CTP C++ 接口 for linux
Bindgen: https://github.com/rust-lang/rust-bindgen

CTP for linux
Rust: Bindgen绑定CTP C++原生接口尝试_第1张图片说明一下,我在windows环境下,同样的方法,一直报libclang没有找到(如下,问题是我明明设置这个环境变量,为什么睁眼看不见),至今也没有解决,看了github bindgen issues上提的问题,类似的问题不少。试了不少方法,终于放弃,转WSL2.
windows下bug:

thread ‘main’ panicked at ‘Unable to find libclang: “couldn’t find any valid shared libraries matching: [‘clang.dll’, ‘libclang.dll’], set the LIBCLANG_PATH environment variable to a path where one of these files can be found (invalid: [])”’, C:\Users\songroom.cargo\registry\src\github.com-1ecc6299db9ec823\bindgen-0.55.1\src/lib.rs:1896:31

在WSL下:这个下面安装clang来解决:

sudo apt-get install llvm
sudo  apt install clang

ctp-sdk文件这个可以找指定的地方copy进来,这部分省略。

总体效果如下:

Rust: Bindgen绑定CTP C++原生接口尝试_第2张图片
二、构建wrapper.hpp 文件

wrapper.hpp是告诉bindgen,我这些都需要帮我翻译一下。东西在这呢。这个文件可以放在src目录下。
注意:加上“…/”; 或者用绝对路径。

#include "../ctp_sdk/ThostFtdcMdApi.h"
#include "../ctp_sdk/ThostFtdcTraderApi.h"
#include "../ctp_sdk/ThostFtdcUserApiStruct.h"
#include "../ctp_sdk/ThostFtdcUserApiDataType.h"

三、倒腾build.rs文件
build.rs文件,放在工程目录的根目录下,我这儿的工程名是“rust_new_test”,build.rs放在和Cargo.toml同一目录级下,并列就好。

use std::env;
use std::path::PathBuf;

fn main() {

    let bindings = bindgen::Builder::default()
        // The input header we would like to generate
        // bindings for.
        .header("src/wrapper.hpp")
        /* // Tell cargo to invalidate the built crate whenever any of the
        // included header files changed.
        .parse_callbacks(Box::new(bindgen::CargoCallbacks)) */
        .ignore_methods()
        .rustified_enum(".*")
        .blacklist_item("CTP_SIDE_TYPE")
        .blacklist_function("TraderSpiStub_Rust.*")
        .blacklist_function("QuoteSpiStub_Rust.*")
        .generate_comments(false)// 不需形成doc ,默认true
        .layout_tests(false) //不需要test,默认true
        .generate_comments(false)//不需注释,默认true
        .derive_copy(false)
        .derive_hash(false) //不要实现hash
        /* .default_enum_style(bindgen::EnumVariation::Rust {
            non_exhaustive: true,
        }) */
        // Finish the builder and generate the bindings.
        .generate()
        // Unwrap the Result and panic on failure.
        .expect("Unable to generate bindings");

// 注意,这些属性尽量要有所控制,否则会在类型转换时造成影响
/*      derive_copy: true, 
        derive_debug: true,
        derive_default: false,
        derive_hash: false,
        derive_partialord: false,
        derive_ord: false,
        derive_partialeq: false,
        derive_eq: false, */

    //OUT_DIR: D:\rust_test\
    // Write the bindings to the $OUT_DIR/bindings.rs file.
    //let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    //r"C:\windows\system32.dll"
    let out_path = PathBuf::from("/home/songroom/rust_new_test");
    println!("out_path: {:?}",out_path);
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("Couldn't write bindings!");
}

blacklist_item、blacklist_function是指哪些不需要进行翻译的项。

需要注意的是,我特地把里面的注释、测试、文档等关闭了(设置了false).具体的设置可以在文档中找到。主要原因是,文档太长了,看了根本吃不消。关闭了大约7000+行,不关闭这些近70000行,你说,能吃得消么?

https://github.com/rust-lang/rust-bindgen/blob/0996486f0977e12f1a64f7730b3eca81659aa839/src/lib.rs
impl Default for BindgenOptions {
    fn default() -> BindgenOptions {
        let rust_target = RustTarget::default();

        BindgenOptions {
            rust_target,
            rust_features: rust_target.into(),
            blacklisted_types: Default::default(),
            blacklisted_functions: Default::default(),
            blacklisted_items: Default::default(),
            opaque_types: Default::default(),
            rustfmt_path: Default::default(),
            whitelisted_types: Default::default(),
            whitelisted_functions: Default::default(),
            whitelisted_vars: Default::default(),
            default_enum_style: Default::default(),
            bitfield_enums: Default::default(),
            newtype_enums: Default::default(),
            rustified_enums: Default::default(),
            rustified_non_exhaustive_enums: Default::default(),
            constified_enums: Default::default(),
            constified_enum_modules: Default::default(),
            default_macro_constant_type: Default::default(),
            default_alias_style: Default::default(),
            type_alias: Default::default(),
            new_type_alias: Default::default(),
            new_type_alias_deref: Default::default(),
            builtins: false,
            emit_ast: false,
            emit_ir: false,
            emit_ir_graphviz: None,
            layout_tests: true,
            impl_debug: false,
            impl_partialeq: false,
            derive_copy: true,
            derive_debug: true,
            derive_default: false,
            derive_hash: false,
            derive_partialord: false,
            derive_ord: false,
            derive_partialeq: false,
            derive_eq: false,
            enable_cxx_namespaces: false,
            enable_function_attribute_detection: false,
            disable_name_namespacing: false,
            disable_nested_struct_naming: false,
            disable_header_comment: false,
            use_core: false,
            ctypes_prefix: None,
            anon_fields_prefix: DEFAULT_ANON_FIELDS_PREFIX.into(),
            namespaced_constants: true,
            msvc_mangling: false,
            convert_floats: true,
            raw_lines: vec![],
            module_lines: HashMap::default(),
            clang_args: vec![],
            input_header: None,
            input_unsaved_files: vec![],
            parse_callbacks: None,
            codegen_config: CodegenConfig::all(),
            conservative_inline_namespaces: false,
            generate_comments: true,
            generate_inline_functions: false,
            whitelist_recursively: true,
            generate_block: false,
            objc_extern_crate: false,
            block_extern_crate: false,
            enable_mangling: true,
            detect_include_paths: true,
            prepend_enum_name: true,
            time_phases: false,
            record_matches: true,
            rustfmt_bindings: true,
            size_t_is_usize: false,
            rustfmt_configuration_file: None,
            no_partialeq_types: Default::default(),
            no_copy_types: Default::default(),
            no_debug_types: Default::default(),
            no_hash_types: Default::default(),
            array_pointers_in_arguments: false,
            wasm_import_module_name: None,
        }
    }
}

四、Cargo.toml

[package]
name = "rust_new_test"
version = "0.1.0"
authors = ["sg"]
edition = "2018"

[dependencies]

lazy_static ="1.4"
libc = "0.2"

[build-dependencies]
bindgen = "0.55.1"
cc = "1.0"

五、lib.rs :视情况

如果Cargo.toml文件中没有lib设置(如下,类似),则lib.rs可以忽略。

[lib]
name ="ctp"
path ="src\lib.rs"

如果有lib设置,lib.rs路径可以设“src\lib.rs”,即放在src目录下,设一个空文件即可。

六、cargo build
输入:

cargo build --release

Rust: Bindgen绑定CTP C++原生接口尝试_第3张图片
注:[这张图为后补充]
这样,binding.rs就自动生成了。
如下图:
文件很大,有几万行,这里就只显示一部分了。
Rust: Bindgen绑定CTP C++原生接口尝试_第4张图片

你可能感兴趣的:(Rust,C++,CTP,rust,c++,开发语言)