【问题标题】:How to compile+link a simple hello_world.c against a "cdylib" Rust lib on Windows using MSVC [duplicate]如何使用 MSVC 在 Windows 上针对“cdylib”Rust lib 编译+链接一个简单的 hello_world.c [重复]
【发布时间】:2020-10-12 12:16:24
【问题描述】:

我使用 Rust (crate type = "cdylib") 创建了一个动态库。 Rust/Cargo 生成了两个文件:text_loading_lib.dlltext_loading_lib.dll.lib。我想在 Windows 上构建一个非常简单的项目 (hello_world.c),它使用这个库中的一个函数,只使用 MSVC(Microsoft Visual C++ 工具集)和 JetBrains CLion/CMake。

ma​​in.c

#include <stdio.h>

typedef unsigned long long usize_t; // 64 bit / usize on 64 bit machine
extern void show_loading_animation_ffi(usize_t, usize_t, int, usize_t (*prog_fn)());

// function that tells the lib how many percent progress we made so far
usize_t progress_reporter() { return (usize_t) 20 }

int main(void) {
    show_loading_animation_ffi(0, 100, TARGET_STDERR, progress_reporter);
    return 0;
}

我熟悉 UNIX 上的这个过程,但我不知道它是如何在 Windows 上完成的。在 UNIX 上,我会在编译期间将共享对象链接到 main.c,并在运行时使用 LD_LIBRARY_PATH 提供其位置。在 Windows 上是否类似?

我还使用 JetBrains CLion 尝试了一个 CMAKE 项目,但仍然没有成功。当我尝试从 CLion 运行 main.c 中的 main() 时,总是会出现无法创建目标的错误。使用 Rust 创建的库文件(text_loading_lib.dlltext_loading_lib.dll.lib)与 CMakeLists.txtmain.c 在同一目录中。

CMakeLists.txt

cmake_minimum_required(VERSION 3.16)
project(main C)

set(CMAKE_C_STANDARD 11)

add_executable(main main.c)

# the path is correct
target_link_libraries(main text_loading_animation)
#also tried: target_link_libraries(main text_loading_animation.dll)
#also tried:  target_link_libraries(main text_loading_animation.dll.lib)

CLion-输出为:

[ 50%] Linking C executable main.exe
LINK Pass 1: command "C:\PROGRA~2\MICROS~2\2019\COMMUN~1\VC\Tools\MSVC\1426~1.288\bin\Hostx64\x64\link.exe /nologo @CMakeFiles\main.dir\objects1.rsp /out:main.exe /implib:main.lib /pdb:C:\dev\lib-text-loading-animation-rust\calling-from-c-examples\windows\cmake-build-debug\main.pdb /version:0.0 /machine:x64 /debug /INCREMENTAL /subsystem:console text_loading_animation.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTFILE:CMakeFiles\main.dir/intermediate.manifest CMakeFiles\main.dir/manifest.res" failed (exit code 1104) with the following output:
LINK : fatal error LNK1104: File "text_loading_animation.lib" can't be opened.
NMAKE : fatal error U1077: ""C:\Program Files\JetBrains\CLion 2020.1.1\bin\cmake\win\bin\cmake.exe"": Return-Code "0xffffffff"
Stop.
NMAKE : fatal error U1077: ""C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\bin\HostX64\x64\nmake.exe"": Rückgabe-Code "0x2"
Stop.
NMAKE : fatal error U1077: ""C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\bin\HostX64\x64\nmake.exe"": Rückgabe-Code "0x2"
Stop.
NMAKE : fatal error U1077: ""C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.26.28801\bin\HostX64\x64\nmake.exe"": Rückgabe-Code "0x2"
Stop.

【问题讨论】:

  • "但还是没有成功"...这到底是什么意思?您是否收到某种错误?如果是这样,具体的错误是什么?顺便说一句,在 CMake 中链接外部库的方法有据可查here。也许,您可以尝试其中一种方法。
  • 当我在 CLION 的 main.c 中运行 main() 时,程序永远不会启动。它总是说“无法创建目标”。 NMAKE:致命错误 U1073:我不明白这一点,因为 rust 创建的库绝对位于 CMakeLists.txt 中的路径
  • 您遇到什么错误?他们会提供帮助。例如,我可以看到您将库名称写为text_loading_animation.DDL.lib 而不是text_loading_animation.DLL.lib。还要记住,在 Windows 上没有 LD_LIBRARY_PATHrpath 等效项。您的 dll 必须与可执行文件位于同一目录中,或者必须位于您的系统路径中。
  • complete 编译输出和错误消息放在您的问题帖子中将有助于理解具体出了什么问题。如前所述,您的库名称中似乎有错字。
  • 我将这两个文件(text_loading_animation.dlltext_loading_animation.dll.lib)复制到与CMakeLists.txtmain.c 相同的目录中。我将 CMakeLists.txt 更改为 target_link_libraries(main text_loading_animation) 上面写着 [ 50%] Linking C executable main.exe LINK Pass 1: command "...link.exe /nologo @CM... LINK : fatal error LNK1104: File "text_loading_animation.lib" can't be opened. NMAKE : fatal error U1077: ""C:\Program Files\JetBrains\CLion 2020.1.1\bin\cmake\win\bin\cmake.exe"": Return-Code "0xffffffff" 但它肯定在这个目录中。

标签: c windows visual-c++ cmake rust


【解决方案1】:

我让它与 CMake 以及命令行一起工作。

Cmake:CMakeLists.txt

cmake_minimum_required(VERSION 3.16)
project(main C)

set(CMAKE_C_STANDARD 11)

add_executable(main main.c)
# "*.dll.lib" - important! not just *.dll
target_link_libraries(main ${CMAKE_CURRENT_SOURCE_DIR}/../../target/release/text_loading_animation.dll.lib)

# copy DLL file into target dir
add_custom_command(TARGET main POST_BUILD              # Adds a post-build event to "main"
    COMMAND ${CMAKE_COMMAND} -E copy_if_different      # which executes "cmake - E copy_if_different..."
    "${PROJECT_SOURCE_DIR}/text_loading_animation.dll" # <--this is in-file
    $<TARGET_FILE_DIR:main>)                           # <--this is out-file path

现在您可以在 Jetbrains CLion 中“运行 main”。


命令行(Windows 批处理脚本)

重要的部分是:

  1. cl main.c /link text_loading_animation.dll.lib
  2. main.exe

完整的批处理脚本:

@echo off

rem: clean old data
del main.exe main.obj *.dll *.dll.lib

rem: copy rust lib into current dir
xcopy /y ..\..\target\release\text_loading_animation.dll .
xcopy /y ..\..\target\release\text_loading_animation.dll.lib .


rem: sets up Visual Studio Compilertoolsuite environment
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"

rem: *.dll.lib contains header information during compile; *.dll is the runtime file that must be in the same directory/path

rem: "cl" is windows compiler: produces main.obj and main.exe; main.obj is not needed in the end;
rem:   it is only for the stage between compiling and linking
rem: /W4 is highest warnings flag
cl /W4 main.c /link text_loading_animation.dll.lib
del main.obj

rem: now execute
main.exe

【讨论】:

  • 除了我之前链接的将外部库添加到 CMake 项目的其他方法之外,您还可以使用 CMake 本身将 DLL 复制到可执行文件夹,如图所示here。无需手动步骤...
  • 有效,谢谢!我编辑我的答案以包括这个。
猜你喜欢
  • 2019-12-30
  • 2021-06-08
  • 1970-01-01
  • 1970-01-01
  • 2019-10-10
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多