精易论坛

标题: RUST编写易语言可调用的dll [打印本页]

作者: 美稀宗    时间: 2023-7-1 22:29
标题: RUST编写易语言可调用的dll
本帖最后由 美稀宗 于 2023-7-2 17:48 编辑

-----------------------------------------20230702----------------------------------------
感谢@等等什么卿
给出了更快速的方案,大家可以参考原帖


https://125.confly.eu.org/thread-14787937-1-1.html


由于我没有得到原贴授权,这里就不贴源码了。感兴趣的可以到原贴看看。不过优化后速度可是快了一个数量级啊。

我之前在代码只是抛砖引玉,这里又让我想到了一点,既然之前要减少内存消耗,是不是该引入迭代器了。



--------------------------------------- 以下为原贴---------------------------------------
[C++] 纯文本查看 复制代码
#[no_mangle]
pub extern "stdcall" fn rustforin() {
    let mut sum = String::new();

    for i in 1..=99 {
        for j in 1..=99 {
            for k in 1..99 {
                if i == j || i == k || j == k {
                } else {

                    sum += &format!("{:02} {:02} {:02}\r\n", i, j, k);
                }
            }
        }
    }
    let mut file = std::fs::File::create("三位数.txt").expect("创建失败");
    file.write_all(sum.as_bytes()).expect("创建失败");
}





由于易语言对10万以上的文本处理循环非常不友好,比如下面这个帖子
https://125.confly.eu.org/forum.php?mod=viewthread&tid=14787065

我写的两种方式都要10多秒到20秒左右才能处理完。
首先新建rust库项目,在命令行输入



cargo new  testdll --lib

在项目目录中找到Cargo.toml文件,打开该文件,直接在最后添加

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

进到src文件夹,打开lis.rs,删掉原有的例子,写你自己的dll

[C++] 纯文本查看 复制代码
use std::io::Write;
#[no_mangle]
pub extern "stdcall" fn rustforin() {
    let mut sum = String::new();
    let mut a;
    let mut b;
    let mut c;
    for i in 1..=99 {
        for j in 1..=99 {
            for k in 1..99 {
                if i == j || i == k || j == k {
                } else {
                    if i < 10 {
                        a = String::from("0") + &i.to_string();
                    } else {
                        a = i.to_string();
                    }
                    if j < 10 {
                        b = String::from("0") + &j.to_string();
                    } else {
                        b = j.to_string();
                    }
                    if k < 10 {
                        c = String::from("0") + &k.to_string();
                    } else {
                        c = k.to_string();
                    }
                    sum = sum + &a + &String::from(" ") + &b + &String::from(" ") + &c + "\r\n";
                }
            }
        }
    }
    let mut file = std::fs::File::create("三位数.txt").expect("创建失败");
    file.write_all(sum.as_bytes()).expect("创建失败");
}


这里要注意函数调用方式
pub extern "stdcall"

最后,编译dll,在命令行输入


cargo build --release --target i686-pc-windows-msvc

红字一定一定要注意,rust默认的是64位编译器,如果直接运行cargo build --release,易语言调用的时候会报错,提示找不到接口。
以下是我的rust配置32位编译器方法,在.cargo文件夹下,找到config.ini,按如下修改,其中linker要选择你自己32位编译器地址。
[target.i686-pc-windows-msvc]
rustflags = ["-C", "target-feature=+crt-static"]
linker = "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx86\x86\link.exe"

ok,到这dll就完事了,现在把dll添加到易语言里调用一下看看
  
DLL命令名返回值类型公开备 注
rustforin 
DLL库文件名:
TestDLL.dll
在DLL库中对应命令名:
rustforin
参数名类 型传址数组备 注


  
子程序名返回值类型公开备 注
_按钮2_被单击  
变量名类 型静态数组备 注
时间整数型 
三位数排列1 ()
三位数排列 ()
调试输出 (“dll,开始”)
时间 = 取启动时间 ()
rustforin ()
调试输出 (取启动时间 () - 时间)
调试输出 (“dll,完成”)


i支持库列表   支持库注释   
spec特殊功能支持库







作者: 小小小小鸟89    时间: 2023-7-2 09:48
用快速文本对象试试 ,易语言本身没啥问题,主要是写法~:
开始运行被调试程序
* “耗时:391”
被调试易程序运行完毕

三位数排列.e

3.76 KB, 下载次数: 1, 下载积分: 精币 -2 枚

快速文本对象


作者: 海洋之心365    时间: 2023-7-3 16:00
菜鸟前来学习 膜拜大佬
作者: kofu1223    时间: 2023-7-7 17:34

作者: yssustore    时间: 2023-7-22 15:52
菜鸟前来学习 膜拜大佬
作者: acd1231    时间: 2023-8-14 17:31

作者: acd1231    时间: 2023-8-14 17:32

作者: acd1231    时间: 2023-8-14 17:32

作者: acd1231    时间: 2023-8-14 17:32

作者: 菜鸟菜鸡秋水    时间: 2023-8-17 21:40
我电脑找到了对应的link.exe ,
但是提示错误,
   Compiling testdll v0.1.0 (E:\b各种语言代码\rustCode\testdll)
error[E0463]: can't find crate for `std`
  |
  = note: the `i686-pc-windows-msvc` target may not be installed
  = help: consider downloading the target with `rustup target add i686-pc-windows-msvc`

error: requires `sized` lang_item

For more information about this error, try `rustc --explain E0463`.

最后用rust 的方法 安装了对应依赖 ,好像编译过了,开心

按照提示  用  rustup target add i686-pc-windows-msvc 安装对应依赖,就好了,
编译结果在  \target\i686-pc-windows-msvc\release  这个目录,有对应dll ,

00.png (148.23 KB, 下载次数: 0)

00.png

作者: 菜鸟菜鸡秋水    时间: 2023-8-19 19:58
想用rust 和易语言交互的兄弟们 ,  这是一个编码库 ,省的大家找 , 本人没有测试 , 是大公司搞的 https://github.com/hsivonen/encoding_rs
作者: 美稀宗    时间: 2023-8-19 23:53
菜鸟菜鸡秋水 发表于 2023-8-19 19:58
想用rust 和易语言交互的兄弟们 ,  这是一个编码库 ,省的大家找 , 本人没有测试 , 是大公司搞的 https://gi ...

这个库在rust上可以显示汉字a码,u码rust可以直接使用
比如,进程名取pid
[C++] 纯文本查看 复制代码
fn getpid_from_name(pname: &str, wordscase: bool, call_back_arry: &mut Vec<u32>) -> i32 {
    let handle: HANDLE;
    let mut pe32 = &mut PROCESSENTRY32W {
        dwSize: 0,
        cntUsage: 0,
        th32ProcessID: 0,
        th32DefaultHeapID: 0,
        th32ModuleID: 0,
        cntThreads: 0,
        th32ParentProcessID: 0,
        pcPriClassBase: 0,
        dwFlags: 0,
        szExeFile: [0; 260],
    };
    unsafe {
        handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0).unwrap();
    }

    pe32.dwSize = size_of::<PROCESSENTRY32W>() as u32;

    unsafe {
        if Process32FirstW(handle, pe32) == false {
            CloseHandle(handle);
            println!("获取进程快照句柄失败");
            return -1;
        }
        while Process32NextW(handle, pe32) != false {
            //println!("进程名为{:?}",pe32.szExeFile);
            let text_wide = String::from_utf16(&pe32.szExeFile).unwrap();
            let process_name = text_wide.trim_end_matches("\0");
            //println!("进程名为{:?}",process_name);
            if wordscase != true {
                let cpname = pname.to_lowercase();
                if cpname == process_name.to_lowercase() {
                    call_back_arry.push(pe32.th32ProcessID as u32);
                }
            } else {
                let cpname = pname.to_string();
                if cpname == process_name.to_string() {
                    call_back_arry.push(pe32.th32ProcessID as u32);
                }
            }
        }
        if CloseHandle(handle) == true {
            println!("关闭成功");
        }
        if call_back_arry.get(0) == None {
            return 0;
        } else {
            return call_back_arry[0] as i32;
        }
    }
}


这里PROCESSENTRY32W直接返回的就是u码,rust可以直接显示,如果易语言要调用这个接口,需转码才能显示。
这个库的好处是,如果涉及到32位读内存文本型(),可以直接返回汉字a码,否则只能通过返回字节数组的形式,即读内存字节集(),再通过到文本()转化为汉字

作者: 菜鸟菜鸡秋水    时间: 2023-8-21 17:07
美稀宗 发表于 2023-8-19 23:53
这个库在rust上可以显示汉字a码,u码rust可以直接使用
比如,进程名取pid
[mw_shl_code=cpp,true]fn getp ...

厉害 , 我都没试过 ,我只是看到了, 这rust  很复杂 ,挺难学 ,
有没有和易语言交互的  dll 案例啊  ?
作者: 美稀宗    时间: 2023-8-21 21:47
菜鸟菜鸡秋水 发表于 2023-8-21 17:07
厉害 , 我都没试过 ,我只是看到了, 这rust  很复杂 ,挺难学 ,
有没有和易语言交互的  dll 案例啊  ? ...

正在写读写内存
作者: 菜鸟菜鸡秋水    时间: 2023-8-21 22:51
美稀宗 发表于 2023-8-21 21:47
正在写读写内存

建立一个交流群 , 一起交流
作者: wukongcch1998    时间: 2023-12-1 22:48
6666666666666666666666666




欢迎光临 精易论坛 (https://125.confly.eu.org/) Powered by Discuz! X3.4