Closed kcrazy closed 1 year ago
I dug a bit around this issue and couldn't figure out when clang
actually decides to use the Default
calling convention. Every example I tried in linux and windows had the C
calling convention and there was no way to distinguish that from functions tagged with the cdecl
attribute for example.
I guess one alternative would be to do this in postprocessing (or even inside codegen I guess) and add a new family of regex options to bindgen so we can set the ABI to whatever we want but I'm not sure that's the right approach as it would change the calling convention arbitrarily without respecting the target or the header inputs.
Any ideas @emilio, @kulp, @amanjeev?
Yeah, so right now we make the assumption that the default ABI is "C": https://github.com/rust-lang/rust-bindgen/blob/63bf6433e10156899e614c73d03ada682ff079ac/bindgen/ir/function.rs#L243
Ideally we'd just do the right thing based on the target. If clang exposes the resolved "default" ABI that'd be preferrable to adding a new option.
But AFAIK CXCallingConv_Default
is not actually returned anywhere by libclang.
Edit: Just wanted to make it clear that I changed exactly that line expecting it would work but it does not :(. Apparently what happens is that this CXCallingConv_Default
variant is defined by clang but not returned anywhere at all so everything is tagged as using the C
calling convention.
Yep, if you check libclang's code, you'll notice that clang_getFunctionTypeCallingConv
actually calls getCallConv
, which at the same time calls getCC
, this last function returns a CallingConv
value (this enum doesn't even have a "default calling convention" variant). This value is built from a Bits
field that by default sets the calling convention to CC_C
.
So no idea where this CXCallingConv_Default
value is used and how.
As a consequence. I think there's no way to distingush a function without any calling convention attributes and one with the cdecl
calling convention attribute.
Given that it seems there's no way to override the default calling convention without changing items that explicitly use the C
calling convention I wonder if we could add a regex option like this:
builder.override_abi("matching_function", ABI::Stdcall);
so this input:
void matching_function();
void other_function();
emits this output:
extern "stdcall" {
fn matching_function();
}
extern "C" {
fn other_function();
}
This would also fix https://github.com/rust-lang/rust-bindgen/issues/2224
Hi, I've been expermenting with Windows driver APIs and Bindgen and stumbled into this thread.
I'm not sure if it's relevant but here are my observations. I'm very new to this so please excuse me if I'm stating the obvious or doing something wrong.
extern "C"
for stdcall when compiling for x64, but extern "system"
for x86..clang_arg("-mrtd")
(stdcall by default) and compiling for x86 seems to generate extern "system"
by default..clang_arg("-mrtd")
and compiling for x64 results in a libclang error.The wrapper file:
#include <10.0.22621.0/um/windows.h>
#include <wdf/umdf/2.33/wdf.h>
// Needs to be compiled as C++
#define IDD_STUB
#include <10.0.22621.0/um/iddcx/1.9/IddCx.h>
and relevant snippets from build.rs (commented lines are variants):
println!("cargo:rustc-link-search=C:/Program Files (x86)/Windows Kits/10/Lib/10.0.22621.0/um/x64/iddcx/1.9");
// println!("cargo:rustc-link-search=C:/Program Files (x86)/Windows Kits/10/Lib/10.0.22621.0/um/x86/iddcx/1.9");
println!("cargo:rustc-link-lib=iddcxstub");
bindgen::Builder::default()
// .clang_arg("--target=i686-pc-windows-msvc")
// .clang_arg("-mrtd")
.clang_arg("--language=c++")
.clang_arg("--include-directory=C:/Program Files (x86)/Windows Kits/10/Include")
.header("wrapper.hpp")
.allowlist_type("DRIVER_INITIALIZE")
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.use_core()
.generate()
As far as I understand, compiling for x64 doesn't differentiate between cdecl and stdcall because they are converted to a different calling convention. So if I understand correctly, I should be able to use extern "C"
against Windows API no matter if it uses cdecl or stdcall as long as I'm compiling for x64?
Also regarding:
the default ABI of the windows kernel is stdcall, so the most functions do not specify ABI.
I'd like to ask where one learns this kind of info because searching for a confirmation of this is what lead me here in the first place.
the default ABI of the windows kernel is stdcall, so the most functions do not specify ABI. Is it possible to increase the default ABI option? example
default_abi(name: &str)
Input C/C++ Header
Bindgen Invocation
Actual Results
Expected Results