< 返回版块

xBINj 发表于 2020-07-24 20:52

Tags:FFI

最前面总结一下我的问题,要不然语文不行没说清楚,还误导别人了,我的问题就是: 在windows 10下,怎么在我的rust exe程序中使用第三方的dll导出的函数,有第三方库的dll和lib文件?

我的电脑环境是:

Windows 10, 开发环境是VS Code,有Cygwin环境,.lib和.dll通过Cygwin编译而成。命令行如下:

 gcc -save-temps -shared test_a.c test_b.c test_c.c -o test.dll

 ar r test.lib test_a.o test_b.o test_c.o

cargo new --lib XXX,创建一个FFI绑定库工程,绑定库功能能编译通过,然后这个FFI绑定库提供给另外的Rust exe工程使用,但是这个exe功能就cargo build不通过,

cargo build一直提示linkXXX错误,如下:

PS C:\cygwin64\home\jjjhh\snappy-rs-test> cargo build Compiling snappy-rs-test v0.1.0 (C:\cygwin64\home\jjjhh\snappy-rs-test) error: linking with link.exe failed: exit code: 1181

| = note: "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.26.28801\bin\HostX64\x64\link.exe" "/NOLOGO" "/NXCOMPAT" "/LIBPATH:C:\Users\jjjhh\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\x86_64-pc-windows-msvc\lib" "C:\cygwin64\home\jjjhh\snappy-rs-test\target\debug\deps\snappy_rs_test.14ubteio49sg8ls7.rcgu.o" "C:\cygwin64\home\jjjhh\snappy-rs-test\target\debug\deps\snappy_rs_test.4q0x2sst8 ................

怀疑是找不到对应的 *.lib,但是我拷贝到/user/jjjhh/.rustup/....里面的lib目录,工程根目录,debug目录,debug/deps目录,均不行。倒腾好久了,求高手指点一二。


我照着论坛的教程 Rust FFI绑定入门,也还是这种错误,但是我的环境是Windows,教程里面好像是 linux。

评论区

写评论
作者 xBINj 2020-07-28 15:10

还有一个警告错误,LNK4272,这个链接警告就是提示”warning LNK4272: 库计算机类型“X86”与目标计算机类型“x64”...“ 居然一直眼瞎没看到,可以结帖了,谢谢各位的大力支持,我也学到了蛮多ffi的东东了。

--
👇
xBINj: 我的问题终于找到根源了,都是我眼瞎,vs build tools默认打开的是x32的,所以编译出来的dll自然是32位的,但是我的系统是64位的,cargo build默认就是64的,难怪一直找不到lib,今天仔细研究了错误信息是LNK2019,也就是找不到lib文件,那就是要么路径不对,要么就是dll或者是lib文件不对,我擦……整整捣鼓了1天多,幸亏用dumpbin看了一下,,没脸说了,的确眼瞎了。

大家可千万别学我啊。。。。唉,欲哭无泪~

作者 xBINj 2020-07-28 14:57

我的问题终于找到根源了,都是我眼瞎,vs build tools默认打开的是x32的,所以编译出来的dll自然是32位的,但是我的系统是64位的,cargo build默认就是64的,难怪一直找不到lib,今天仔细研究了错误信息是LNK2019,也就是找不到lib文件,那就是要么路径不对,要么就是dll或者是lib文件不对,我擦……整整捣鼓了1天多,幸亏用dumpbin看了一下,,没脸说了,的确眼瞎了。

大家可千万别学我啊。。。。唉,欲哭无泪~

作者 xBINj 2020-07-27 14:36

let profile = std::env::var("PROFILE").unwrap(); 这行代码异常,没找到PROFILE变量,囧。。。这变量作什么的?

--
👇
xBINj: 还是出错,要哭,我都怀疑我的dll是不是有问题了。

出错信息如下:

error: linking with link.exe failed: exit code: 1181 | = note: "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.26.28801\bin\HostX64\x64\link.exe" "/NOLOGO" "/NXCOMPAT" "/LIBPATH:C:\Users\jjjhh\.r

--
👇
ywxt: Windows 上的动态库是dll

main.rs

use std::os::raw::{c_int, c_char};
use std::ffi::{CString};
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
    println!("Hello, world!");
    unsafe {
        let text = CString::new("Hello")?;
        // 调用win32 函数
        MessageBoxA(0, text.as_ptr(), text.as_ptr(), 0);
        // 调用自定义函数
        test();
    }

    Ok(())
}

#[link(name = "User32")]
extern "stdcall" {
    fn MessageBoxA(hwnd: c_int, text: *const c_char, title: *const c_char, flags: c_int) -> c_int;
}
#[link(name = "testlib")]
extern {
    fn test();
}

build.rs

use std::path::PathBuf;

fn main() {
    let project = std::env::var("CARGO_MANIFEST_DIR").unwrap();
    // 指定库的位置
    println!("cargo:rustc-link-search={}", project);


    // 以下 复制testlib到输出目录
    let profile = std::env::var("PROFILE").unwrap();
    let mut output_dir = PathBuf::new();
    output_dir.push(&project);
    output_dir.push("target");
    output_dir.push(&profile);
    let mut dll_target = output_dir.clone();
    dll_target.push("testlib.dll");
    let mut dll_source = PathBuf::from(&project);
    dll_source.push("testlib.dll");
    if !dll_target.exists() {
        std::fs::copy(&dll_source,&dll_target).unwrap();
    }

}

把testlib.dll 放到 项目目录下

作者 xBINj 2020-07-27 10:38

还是出错,要哭,我都怀疑我的dll是不是有问题了。

出错信息如下:

error: linking with link.exe failed: exit code: 1181 | = note: "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.26.28801\bin\HostX64\x64\link.exe" "/NOLOGO" "/NXCOMPAT" "/LIBPATH:C:\Users\jjjhh\.r

--
👇
ywxt: Windows 上的动态库是dll

main.rs

use std::os::raw::{c_int, c_char};
use std::ffi::{CString};
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
    println!("Hello, world!");
    unsafe {
        let text = CString::new("Hello")?;
        // 调用win32 函数
        MessageBoxA(0, text.as_ptr(), text.as_ptr(), 0);
        // 调用自定义函数
        test();
    }

    Ok(())
}

#[link(name = "User32")]
extern "stdcall" {
    fn MessageBoxA(hwnd: c_int, text: *const c_char, title: *const c_char, flags: c_int) -> c_int;
}
#[link(name = "testlib")]
extern {
    fn test();
}

build.rs

use std::path::PathBuf;

fn main() {
    let project = std::env::var("CARGO_MANIFEST_DIR").unwrap();
    // 指定库的位置
    println!("cargo:rustc-link-search={}", project);


    // 以下 复制testlib到输出目录
    let profile = std::env::var("PROFILE").unwrap();
    let mut output_dir = PathBuf::new();
    output_dir.push(&project);
    output_dir.push("target");
    output_dir.push(&profile);
    let mut dll_target = output_dir.clone();
    dll_target.push("testlib.dll");
    let mut dll_source = PathBuf::from(&project);
    dll_source.push("testlib.dll");
    if !dll_target.exists() {
        std::fs::copy(&dll_source,&dll_target).unwrap();
    }

}

把testlib.dll 放到 项目目录下

作者 xBINj 2020-07-27 10:02

这个是静态的,但是怎么能在windows下链接到第三方动态库dll呢??

--
👇
xBINj: 你这个方法成功了,刚试了。谢谢~

--
👇
ywxt: 你也可以按照这种方式静态链接 https://doc.rust-lang.org/cargo/reference/build-script-examples.html#building-a-native-library

作者 xBINj 2020-07-27 10:01

Windows下,动态链接到dll,你可以忽略我提到的Cygwin的事情。 抱歉。。。是我没说清楚问题,Sorry~

--
👇
gwy15: 没懂你在说什么……

论坛里面说的是linux下动态链接,你都没说清楚你要动态链接还是静态链接,是哪个库调用哪个库。

win下静态链接是lib,动态链接是dll,linux是a和so。

作者 xBINj 2020-07-27 10:00

我就是用dll啊,*.lib文件也有了,但是就是出现link.exe 错误。。。。

--
👇
Mike Tang: 你不是应该用dll吗?

作者 xBINj 2020-07-27 09:52

你这个方法成功了,刚试了。谢谢~

--
👇
ywxt: 你也可以按照这种方式静态链接 https://doc.rust-lang.org/cargo/reference/build-script-examples.html#building-a-native-library

作者 xBINj 2020-07-27 08:45

我的环境是在Windows,但是我没有Visual Studio,所以我就用了Cygwin来编译了。

--
👇
gwy15: 没懂你在说什么……

论坛里面说的是linux下动态链接,你都没说清楚你要动态链接还是静态链接,是哪个库调用哪个库。

win下静态链接是lib,动态链接是dll,linux是a和so。

ywxt 2020-07-25 23:50

你也可以按照这种方式静态链接 https://doc.rust-lang.org/cargo/reference/build-script-examples.html#building-a-native-library

ywxt 2020-07-25 23:10

Windows 上的动态库是dll

main.rs

use std::os::raw::{c_int, c_char};
use std::ffi::{CString};
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
    println!("Hello, world!");
    unsafe {
        let text = CString::new("Hello")?;
        // 调用win32 函数
        MessageBoxA(0, text.as_ptr(), text.as_ptr(), 0);
        // 调用自定义函数
        test();
    }

    Ok(())
}

#[link(name = "User32")]
extern "stdcall" {
    fn MessageBoxA(hwnd: c_int, text: *const c_char, title: *const c_char, flags: c_int) -> c_int;
}
#[link(name = "testlib")]
extern {
    fn test();
}

build.rs

use std::path::PathBuf;

fn main() {
    let project = std::env::var("CARGO_MANIFEST_DIR").unwrap();
    // 指定库的位置
    println!("cargo:rustc-link-search={}", project);


    // 以下 复制testlib到输出目录
    let profile = std::env::var("PROFILE").unwrap();
    let mut output_dir = PathBuf::new();
    output_dir.push(&project);
    output_dir.push("target");
    output_dir.push(&profile);
    let mut dll_target = output_dir.clone();
    dll_target.push("testlib.dll");
    let mut dll_source = PathBuf::from(&project);
    dll_source.push("testlib.dll");
    if !dll_target.exists() {
        std::fs::copy(&dll_source,&dll_target).unwrap();
    }

}

把testlib.dll 放到 项目目录下

ywxt 2020-07-25 21:33

你既然有cygwin,为什么还要用msvc工具链呢?

gwy15 2020-07-25 00:05

没懂你在说什么……

论坛里面说的是linux下动态链接,你都没说清楚你要动态链接还是静态链接,是哪个库调用哪个库。

win下静态链接是lib,动态链接是dll,linux是a和so。

Mike Tang 2020-07-24 21:37

你不是应该用dll吗?

1 共 14 条评论, 1 页