Skip to content

Instantly share code, notes, and snippets.

@tatsuya6502
Last active April 17, 2022 06:20
Show Gist options
  • Save tatsuya6502/f620389322f6bb65f355f84c7a1ecbed to your computer and use it in GitHub Desktop.
Save tatsuya6502/f620389322f6bb65f355f84c7a1ecbed to your computer and use it in GitHub Desktop.
Rust FFI on Windows MSVC
/target/
**/*.rs.bk
Cargo.lock
*.exe
*.obj
exports.txt

Rust FFI: Calling a Rust function from a C program

Environment

C:\Users\tatsuya>rustc --version
rustc 1.20.0 (f3d6973f4 2017-08-27)

C:\Users\tatsuya>rustup run nightly rustc --version
rustc 1.22.0-nightly (277476c4f 2017-09-16)

C:\Users\tatsuya>link
Microsoft (R) Incremental Linker Version 14.11.25507.1
Copyright (C) Microsoft Corporation.  All rights reserved.
...

C:\Users\tatsuya>cl
Microsoft (R) C/C++ Optimizing Compiler Version 19.11.25507.1 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

usage: cl [ option... ] filename... [ /link linkoption... ]

Building and Running

cargo build --release does not emit an import library (.lib) but only creates .dll. To make the C++ compile (cl.ext) to link with the .dll, I had to create .lib from .dll using several commands like dumpbin and lib.

**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.0.26730.12
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'

C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools>cd \Users\tatsuya\ffi

C:\Users\tatsuya\ffi>cargo build --release
   Compiling ffi v0.1.0 (file:///C:/Users/tatsuya/ffi)
    Finished release [optimized] target(s) in 0.51 secs

C:\Users\tatsuya\ffi>dir .\target\release
 Volume in drive C has no label.
 Volume Serial Number is 96D9-58A2

 Directory of C:\Users\tatsuya\ffi\target\release

2017/09/17  19:17    <DIR>          .
2017/09/17  19:17    <DIR>          ..
2017/09/17  19:17                 0 .cargo-lock
2017/09/17  19:17    <DIR>          .fingerprint
2017/09/17  19:17    <DIR>          build
2017/09/17  19:17    <DIR>          deps
2017/09/17  19:17    <DIR>          examples
2017/09/17  19:17                77 ffi.d
2017/09/17  19:17           111,616 ffi.dll
2017/09/17  19:17    <DIR>          incremental
2017/09/17  19:17    <DIR>          native
               3 File(s)        111,693 bytes
               8 Dir(s)  44,607,131,648 bytes free

C:\Users\tatsuya\ffi>dumpbin /Exports target\release\ffi.dll > exports.txt

C:\Users\tatsuya\ffi>echo LIBRARY FFI > ffi.def

C:\Users\tatsuya\ffi>echo EXPORTS >> ffi.def

C:\Users\tatsuya\ffi>for /f "skip=19 tokens=4" %A in (exports.txt) do echo %A >> ffi.def

...

C:\Users\tatsuya\ffi>type ffi.def
LIBRARY FFI
EXPORTS
__rdl_alloc
__rdl_alloc_excess
__rdl_alloc_zeroed
__rdl_dealloc
__rdl_grow_in_place
__rdl_oom
__rdl_realloc
__rdl_realloc_excess
__rdl_shrink_in_place
__rdl_usable_size
pow
rust_eh_personality

C:\Users\tatsuya\ffi>lib /Def:ffi.def /Out:target\release\ffi.lib /Machine:x64
Microsoft (R) Library Manager Version 14.11.25507.1
Copyright (C) Microsoft Corporation.  All rights reserved.
   Creating library target\release\ffi.lib and object target\release\ffi.exp

C:\Users\tatsuya\ffi>cl /EHsc c_src\main.c .\target\release\ffi.lib
Microsoft (R) C/C++ Optimizing Compiler Version 19.11.25507.1 for x64
Copyright (C) Microsoft Corporation.  All rights reserved.

main.c
Microsoft (R) Incremental Linker Version 14.11.25507.1
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:main.exe
main.obj
.\target\release\ffi.lib

C:\Users\tatsuya\ffi>set PATH=.\target\release;%PATH%

C:\Users\tatsuya\ffi>.\main.exe
100

Link Arguments

Maybe there is a way to emit .lib from MSVC?

C:\Users\tatsuya\ffi>set RUSTFLAGS=-Z print-link-args

C:\Users\tatsuya\ffi>cargo +nightly build --release
   Compiling ffi v0.1.0 (file:///C:/Users/tatsuya/ffi)
"C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\BuildTools\\VC\\Tools\\MSVC\\14.11.25503\\bin\\HostX64\\x64\\link.exe"
  "/NOLOGO"
  "/NXCOMPAT"
  "/LIBPATH:C:\\Users\\tatsuya\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-msvc\\lib"
  "C:\\Users\\tatsuya\\ffi\\target\\release\\deps\\ffi.0.o"
  "/OUT:C:\\Users\\tatsuya\\ffi\\target\\release\\deps\\ffi.dll" 
  "/DEF:C:\\Users\\tatsuya\\AppData\\Local\\Temp\\rustc.WXmH6dixFUrY\\lib.def" 
  "C:\\Users\\tatsuya\\ffi\\target\\release\\deps\\ffi.crate.allocator.o"
  "/OPT:REF,ICF"
  "/DEBUG" 
  "/NATVIS:C:\\Users\\tatsuya\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\etc\\liballoc.natvis" 
  "/NATVIS:C:\\Users\\tatsuya\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\etc\\libcore.natvis" 
  "/LIBPATH:C:\\Users\\tatsuya\\ffi\\target\\release\\deps"
  "/LIBPATH:C:\\Users\\tatsuya\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-msvc\\lib" 
  "C:\\Users\\tatsuya\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-msvc\\lib\\libstd-db6de5af2d0a9c77.rlib"
  "C:\\Users\\tatsuya\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-msvc\\lib\\liballoc_system-01640051e83829a3.rlib"
  "C:\\Users\\tatsuya\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-msvc\\lib\\librand-1691a4817e1014c0.rlib"
  "C:\\Users\\tatsuya\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-msvc\\lib\\libpanic_unwind-fe3db6e00272232d.rlib"
  "C:\\Users\\tatsuya\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-msvc\\lib\\liblibc-1bcdb4f089768c3e.rlib"
  "C:\\Users\\tatsuya\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-msvc\\lib\\liballoc-256d8904b26e3f9f.rlib"
  "C:\\Users\\tatsuya\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-msvc\\lib\\libstd_unicode-e1b478fb207a2cfd.rlib"
  "C:\\Users\\tatsuya\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-msvc\\lib\\libunwind-b58e94042876ce0c.rlib"
  "C:\\Users\\tatsuya\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-msvc\\lib\\libcore-3837fbddd99d1fca.rlib"
  "C:\\Users\\tatsuya\\.rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\\lib\\rustlib\\x86_64-pc-windows-msvc\\lib\\libcompiler_builtins-b0347d25dae429a5.rlib"
  "advapi32.lib"
  "ws2_32.lib"
  "userenv.lib"
  "shell32.lib"
  "msvcrt.lib"
  "/DLL"
  "/IMPLIB:C:\\Users\\tatsuya\\ffi\\target\\release\\deps\\ffi.dll.lib"
    Finished release [optimized] target(s) in 0.64 secs

C:\Users\tatsuya\ffi>
#include <stdio.h>
#include <stdint.h>
int32_t
pow(int32_t n);
int
main()
{
int32_t n = 10;
int32_t ret;
ret = pow(n);
printf("%d\n", ret);
}
[package]
name = "ffi"
version = "0.1.0"
authors = ["Tatsuya Kawano <[email protected]>"]
[lib]
crate-type = ["cdylib"]
[dependencies]
#[no_mangle]
pub extern "C" fn pow(n: i32) -> i32 {
n * n
}
@James2022-rgb
Copy link

James2022-rgb commented Apr 17, 2022

cargo build --release does not emit an import library (.lib) but only creates .dll.

Does specifying crate-type = ["staticlib"] instead of "cdylib" help ?

@tatsuya6502
Copy link
Author

Hi. Thank you for your comment. I forgot to update this Gist but I actually fixed the issue by submitting a pull request to the Cargo project:

I think the PR was merged for Cargo v0.23.0 (released on Nov 29, 2017).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment