diff --git a/bindgen-tests/tests/expectations/tests/dynamic_loading_template.rs b/bindgen-tests/tests/expectations/tests/dynamic_loading_template.rs index 65f079bede..1f63a7893f 100644 --- a/bindgen-tests/tests/expectations/tests/dynamic_loading_template.rs +++ b/bindgen-tests/tests/expectations/tests/dynamic_loading_template.rs @@ -20,8 +20,8 @@ impl TestLib { L: Into<::libloading::Library>, { let __library = library.into(); - let foo = __library.get(b"foo\0").map(|sym| *sym); - let foo1 = __library.get(b"foo1\0").map(|sym| *sym); + let foo = __library.get(b"_Z3fooIiET_S0_\0").map(|sym| *sym); + let foo1 = __library.get(b"_Z3fooIfET_S0_\0").map(|sym| *sym); Ok(TestLib { __library, foo, foo1 }) } pub unsafe fn foo(&self, x: ::std::os::raw::c_int) -> ::std::os::raw::c_int { diff --git a/bindgen-tests/tests/expectations/tests/dynamic_loading_with_allowlist.rs b/bindgen-tests/tests/expectations/tests/dynamic_loading_with_allowlist.rs index e65176b863..34ebe8d9a5 100644 --- a/bindgen-tests/tests/expectations/tests/dynamic_loading_with_allowlist.rs +++ b/bindgen-tests/tests/expectations/tests/dynamic_loading_with_allowlist.rs @@ -27,9 +27,9 @@ impl TestLib { L: Into<::libloading::Library>, { let __library = library.into(); - let foo = __library.get(b"foo\0").map(|sym| *sym); - let baz = __library.get(b"baz\0").map(|sym| *sym); - let bazz = __library.get(b"bazz\0").map(|sym| *sym); + let foo = __library.get(b"_Z3fooPv\0").map(|sym| *sym); + let baz = __library.get(b"_Z3bazPv\0").map(|sym| *sym); + let bazz = __library.get(b"_Z4bazziz\0").map(|sym| *sym); Ok(TestLib { __library, foo, diff --git a/bindgen-tests/tests/expectations/tests/dynamic_loading_with_blocklist.rs b/bindgen-tests/tests/expectations/tests/dynamic_loading_with_blocklist.rs index b214d0ef4e..8c86674f7a 100644 --- a/bindgen-tests/tests/expectations/tests/dynamic_loading_with_blocklist.rs +++ b/bindgen-tests/tests/expectations/tests/dynamic_loading_with_blocklist.rs @@ -62,8 +62,8 @@ impl TestLib { L: Into<::libloading::Library>, { let __library = library.into(); - let foo = __library.get(b"foo\0").map(|sym| *sym); - let bar = __library.get(b"bar\0").map(|sym| *sym); + let foo = __library.get(b"_Z3fooPv\0").map(|sym| *sym); + let bar = __library.get(b"_Z3barPv\0").map(|sym| *sym); Ok(TestLib { __library, foo, bar }) } pub unsafe fn foo(&self, x: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int { diff --git a/bindgen-tests/tests/expectations/tests/dynamic_loading_with_class.rs b/bindgen-tests/tests/expectations/tests/dynamic_loading_with_class.rs index 6395b0c6d3..65ff2b2f72 100644 --- a/bindgen-tests/tests/expectations/tests/dynamic_loading_with_class.rs +++ b/bindgen-tests/tests/expectations/tests/dynamic_loading_with_class.rs @@ -59,8 +59,8 @@ impl TestLib { L: Into<::libloading::Library>, { let __library = library.into(); - let foo = __library.get(b"foo\0").map(|sym| *sym); - let bar = __library.get(b"bar\0").map(|sym| *sym); + let foo = __library.get(b"_Z3fooPv\0").map(|sym| *sym); + let bar = __library.get(b"_Z3barv\0").map(|sym| *sym); Ok(TestLib { __library, foo, bar }) } pub unsafe fn foo(&self, x: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int { diff --git a/bindgen/codegen/dyngen.rs b/bindgen/codegen/dyngen.rs index 410cc0d6cb..76f3805795 100644 --- a/bindgen/codegen/dyngen.rs +++ b/bindgen/codegen/dyngen.rs @@ -131,6 +131,7 @@ impl DynamicItems { pub(crate) fn push_func( &mut self, ident: &Ident, + symbol: &str, abi: ClangAbi, is_variadic: bool, is_required: bool, @@ -181,11 +182,12 @@ impl DynamicItems { } // N.B: Unwrap the signature upon construction if it is required to be resolved. - let ident_str = codegen::helpers::ast_ty::cstr_expr(ident.to_string()); + let symbol_cstr = + codegen::helpers::ast_ty::cstr_expr(symbol.to_string()); let library_get = if ctx.options().wrap_unsafe_ops { - quote!(unsafe { __library.get(#ident_str) }) + quote!(unsafe { __library.get(#symbol_cstr) }) } else { - quote!(__library.get(#ident_str)) + quote!(__library.get(#symbol_cstr)) }; self.constructor_inits.push(if is_required { @@ -206,6 +208,7 @@ impl DynamicItems { pub fn push_var( &mut self, ident: &Ident, + symbol: &str, ty: &TokenStream, is_required: bool, wrap_unsafe_ops: bool, @@ -231,12 +234,13 @@ impl DynamicItems { } }); - let ident_str = codegen::helpers::ast_ty::cstr_expr(ident.to_string()); + let symbol_cstr = + codegen::helpers::ast_ty::cstr_expr(symbol.to_string()); let library_get = if wrap_unsafe_ops { - quote!(unsafe { __library.get::<*mut #ty>(#ident_str) }) + quote!(unsafe { __library.get::<*mut #ty>(#symbol_cstr) }) } else { - quote!(__library.get::<*mut #ty>(#ident_str)) + quote!(__library.get::<*mut #ty>(#symbol_cstr)) }; let qmark = if is_required { quote!(?) } else { quote!() }; diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs index ccf632535e..f58a234117 100644 --- a/bindgen/codegen/mod.rs +++ b/bindgen/codegen/mod.rs @@ -779,20 +779,20 @@ impl CodeGenerator for Var { } } } else { - // If necessary, apply a `#[link_name]` attribute - if let Some(link_name) = self.link_name() { - attrs.push(attributes::link_name::(link_name)); - } else { + let symbol: &str = self.link_name().unwrap_or_else(|| { let link_name = self.mangled_name().unwrap_or_else(|| self.name()); - if !utils::names_will_be_identical_after_mangling( + if utils::names_will_be_identical_after_mangling( &canonical_name, link_name, None, ) { + canonical_name.as_str() + } else { attrs.push(attributes::link_name::(link_name)); + link_name } - } + }); let maybe_mut = if self.is_const() { quote! {} @@ -816,6 +816,7 @@ impl CodeGenerator for Var { if ctx.options().dynamic_library_name.is_some() { result.dynamic_items().push_var( &canonical_ident, + symbol, &self .ty() .to_rust_ty_or_opaque(ctx, &()) @@ -4639,21 +4640,19 @@ impl CodeGenerator for Function { write!(&mut canonical_name, "{times_seen}").unwrap(); } - let mut has_link_name_attr = false; - if let Some(link_name) = self.link_name() { - attributes.push(attributes::link_name::(link_name)); - has_link_name_attr = true; - } else { - let link_name = mangled_name.unwrap_or(name); - if !is_dynamic_function && - !utils::names_will_be_identical_after_mangling( - &canonical_name, - link_name, - Some(abi), - ) - { + let link_name_attr = self.link_name().or_else(|| { + let mangled_name = mangled_name.unwrap_or(name); + (!utils::names_will_be_identical_after_mangling( + &canonical_name, + mangled_name, + Some(abi), + )) + .then(|| mangled_name) + }); + + if let Some(link_name) = link_name_attr { + if !is_dynamic_function { attributes.push(attributes::link_name::(link_name)); - has_link_name_attr = true; } } @@ -4665,8 +4664,9 @@ impl CodeGenerator for Function { quote! { #[link(wasm_import_module = #name)] } }); - let should_wrap = - is_internal && ctx.options().wrap_static_fns && !has_link_name_attr; + let should_wrap = is_internal && + ctx.options().wrap_static_fns && + link_name_attr.is_none(); if should_wrap { let name = canonical_name.clone() + ctx.wrap_static_fns_suffix(); @@ -4732,11 +4732,14 @@ impl CodeGenerator for Function { // If we're doing dynamic binding generation, add to the dynamic items. if is_dynamic_function { + let ident_str = ident.to_string(); + let symbol = link_name_attr.unwrap_or(&ident_str); let args_identifiers = utils::fnsig_argument_identifiers(ctx, signature); let ret_ty = utils::fnsig_return_ty(ctx, signature); result.dynamic_items().push_func( &ident, + symbol, abi, signature.is_variadic(), ctx.options().dynamic_link_require_all,