Summary

Extend

拡張する
the #[link] attribute by adding
たす
a new kind kind="raw-dylib" for use on Windows which emits idata sections
for the items in the attached extern block, so they may be linked against without linking against an import library. Also add a #[link_ordinal] attribute for specifying
特定する、指定する、規定する
symbols that are actually ordinals.

Motivation

Traditionally, to link against a dll, the program must actually link against an import library. For example to depend on some symbols from kernel32.dll the program links to kernel32.lib. However, this requires that the correct import libraries be available to link against, and for third party libraries that are only distributed as a dll creating an import library can be quite difficult, especially given

与えられた
that lib.exe is incapable of creating an import library that links to stdcall symbols.

A real advantage of this feature, however, is the fact that symbols will be guaranteed

保証する
to come from the specified
特定する、指定する、規定する
dll. Currently, linking is a very finnicky process where if multiple
複数の
libraries provide the same symbol the linker will choose one of them to provide the symbol and the user has little control
制御する
over it. With kind="raw-dylib" the user is ensured that the symbol will come from the specified
特定する、指定する、規定する
dll.

Sometimes, a crate may know exactly

正確に
which dll it wants to link against, but which import library it ends up linking against is unknown. In particular the d3dcompiler.lib provided
与える
by the Windows SDK can link to several different versions of the d3dcompiler dll depending on which version of the Windows SDK the user has installed. kind="raw-dylib" would allow
許可する、可能にする
winapi to link to a specific
特定の
version of that dll and ensure
保証する
the symbols are correct for that version.

This would also allow

許可する、可能にする
winapi to not have to bundle import libraries for the pc-windows-gnu targets, saving on bandwidth and disk space for users.

Guide-level explanation

When trying to link to a Windows dll, the dylib kind may sometimes be unsuitable, and kind="raw-dylib" can be used instead. A central requirement of kind="raw-dylib" is that the dll has a stable ABI. Here are some examples of valid

有効な、正しい
reasons to use kind="raw-dylib":

  • You've had it up to here with trying to create an import library for a dll that has stdcall functions.
  • You're in linking hell with multiple
    複数の
    import libraries providing
    与える
    the same symbol but from different dlls.
  • You know exactly
    正確に
    which dll you need a symbol from, but you don't know which version of the dll the import library is going to give you.
  • You maintain winapi.

Here is an example of usage:

#![allow(unused)] fn main() { #[cfg(windows)] #[link(name = "kernel32.dll", kind = "raw-dylib")] #[allow(non_snake_case)] extern "system" { fn GetStdHandle(nStdHandle: u32) -> *mut u8; } }

Some symbols are only exported by ordinal from the dll in which case #[link_ordinal(..)] may be used:

#![allow(unused)] fn main() { #[cfg(windows)] #[link(name = "ws2_32.dll", kind = "raw-dylib")] #[allow(non_snake_case)] extern "system" { #[link_ordinal(116)] fn WSACleanup() -> i32; } }

Reference-level explanation

Add a new attribute #[link_ordinal] taking

とる
a single
単一の
unsuffixed integer
整数
value, such as #[link_ordinal(116)]. It can only be specified
特定する、指定する、規定する
on symbols in an extern block using kind="raw-dylib".

Add a new possible value raw-dylib to the kind property

特徴、性質
of the link attribute. When this kind is specified,
特定する、指定する、規定する
the name must explicitly
明示的に
include the extension. In addition,
追加
for all items in the associated
関連付けられた
extern block, Rust will keep the symbol mangled, instead of having an unmangled symbol. Rust will emit an idata section
that maps from the mangled symbol to a symbol in the specified
特定する、指定する、規定する
dll. The symbol in the dll that the idata section
maps to depends on which attributes are specified
特定する、指定する、規定する
on the item in question:

  • If #[link_ordinal] is specified
    特定する、指定する、規定する
    the idata section
    will map from the mangled symbol to the ordinal specified
    特定する、指定する、規定する
    in the dll.
  • If #[link_name] is specified
    特定する、指定する、規定する
    the idata section
    will map from the mangled symbol to the name specified
    特定する、指定する、規定する
    in the dll, without any calling
    呼び出し
    convention decorations added.
    たす
    If calling
    呼び出し
    convention decorations are desired they must be specified
    特定する、指定する、規定する
    explicitly
    明示的に
    in the value of the #[link_name] attribute.
  • If both #[link_ordinal] and #[link_name] are specified,
    特定する、指定する、規定する
    an error will be emitted.
  • If neither #[link_ordinal] nor #[link_name] are specified,
    特定する、指定する、規定する
    the idata section
    will map from the mangled symbol to its unmangled equivalent
    等価
    in the dll. The unmangled symbol will not have calling
    呼び出し
    convention decorations.
  • If #[no_mangle] is specified
    特定する、指定する、規定する
    an error will be emitted.

The idata section

that is produced
産出、産出する
is equivalent
等価
to the idata sections
found in import libraries, and should result
結果、戻り値
in identical
同一の(である)
code generation by the linker.

Drawbacks

Additional

追加の
complexity in the language
言語
through a new kind and a new attribute for specifying
特定する、指定する、規定する
ordinals.

Rationale and alternatives
代わりのもの、選択肢

The RFC as proposed would allow

許可する、可能にする
for full control
制御する
over linking to symbols from dlls with syntax
文法
as close as possible to existing extern blocks.

No alternatives

代わりのもの、選択肢
are currently known other than the status quo.

Prior art

Many non-native languages

言語
have the ability to import symbols from dlls, but this uses runtime loading by the language
言語
runtime and is not the same as what is being proposed here.

Delphi is a native language

言語
that has the ability to import symbols from dlls without import libraries.

Unresolved questions

Whether there are any unresolved questions is an unresolved question.

Future possibilities

  • With the features described
    記述する
    in this RFC, we would be one step closer towards a fully
    完全に
    standalone pure Rust target for Windows that does not rely on any external libraries (aside from the obvious and unavoidable runtime dependence on system libraries), allowing
    許可する、可能にする
    for easy installation and easy cross compilation.
    • If that were to happen, we'd no longer need to pretend the pc-windows-gnu toolchain is standalone, and we'd be able to stop bundling MinGW bits entirely in favor of the user's own MinGW installation, thereby resolving a bunch of issues such as rust-lang/rust#53454.
    • Also with that pure Rust target users would stop complaining about having to install several gigabytes of VC++ just to link their Rust binaries.
      2進数
  • A future extension of this feature would be the ability to optionally lazily load such external functions, since Rust would naturally have all the information required to do so. This would allow
    許可する、可能にする
    users to use functions that may not exist, and be able to write fallback code for older versions.
  • Another future extension would be to extend
    拡張する
    this feature to support shared libraries on other platform, as they could also benefit from the ability to be more precise about linking. For example, on Linux and other platforms using ELF shared libraries, the compiler would emit an ELF NEEDED entry
    項目
    for the specified
    特定する、指定する、規定する
    shared library name, and an undefined symbol for each function declared.
    宣言
    (On ELF platforms, using the link_ordinal attribute would produce
    産出する
    an error.) On such platforms, the link_name attribute may also specify
    特定する、指定する、規定する
    a symbol name that includes a symbol version, including the @@.
    • Windows, however, should be the priority and figuring out details of support for other platforms should not block implementation
      実装
      and stabilization of this feature on Windows.