generate bindings for non-public extern items

Signed-off-by: Marin Veršić <marin.versic101@gmail.com>
This commit is contained in:
Marin Veršić
2023-07-19 10:44:41 +02:00
committed by Emilio Cobos Álvarez
parent acb1b8d89e
commit 5f235ec199
8 changed files with 130 additions and 73 deletions
+6 -4
View File
@@ -4,8 +4,6 @@
use std::io::Write;
use syn::ext::IdentExt;
use crate::bindgen::cdecl;
use crate::bindgen::config::Config;
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
@@ -26,7 +24,11 @@ pub struct Static {
}
impl Static {
pub fn load(item: &syn::ItemStatic, mod_cfg: Option<&Cfg>) -> Result<Static, String> {
pub fn load(
path: Path,
item: &syn::ItemStatic,
mod_cfg: Option<&Cfg>,
) -> Result<Static, String> {
let ty = Type::load(&item.ty)?;
if ty.is_none() {
@@ -34,7 +36,7 @@ impl Static {
}
Ok(Static::new(
Path::new(item.ident.unraw().to_string()),
path,
ty.unwrap(),
item.mutability.is_some(),
Cfg::append(mod_cfg, Cfg::load(&item.attrs)),
+30 -66
View File
@@ -18,7 +18,7 @@ use crate::bindgen::ir::{
AnnotationSet, Cfg, Constant, Documentation, Enum, Function, GenericParam, GenericParams,
ItemMap, OpaqueItem, Path, Static, Struct, Type, Typedef, Union,
};
use crate::bindgen::utilities::{SynAbiHelpers, SynAttributeHelpers, SynItemFnHelpers};
use crate::bindgen::utilities::{SynAbiHelpers, SynAttributeHelpers, SynItemHelpers};
const STD_CRATES: &[&str] = &[
"std",
@@ -643,7 +643,6 @@ impl Parse {
item,
Some(self_type),
&item.sig,
&item.vis,
&item.attrs,
)
}
@@ -665,7 +664,6 @@ impl Parse {
item,
None,
&item.sig,
&item.vis,
&item.attrs,
);
}
@@ -677,10 +675,9 @@ impl Parse {
binding_crate_name: &str,
crate_name: &str,
mod_cfg: Option<&Cfg>,
named_symbol: &dyn SynItemFnHelpers,
named_symbol: &dyn SynItemHelpers,
self_type: Option<&Path>,
sig: &syn::Signature,
vis: &syn::Visibility,
attrs: &[syn::Attribute],
) {
if !config
@@ -707,53 +704,29 @@ impl Parse {
let is_extern_c = sig.abi.is_omitted() || sig.abi.is_c();
let exported_name = named_symbol.exported_name();
if let syn::Visibility::Public(_) = vis {
match (is_extern_c, exported_name) {
(true, Some(exported_name)) => {
let path = Path::new(exported_name);
match Function::load(path, self_type, sig, false, attrs, mod_cfg) {
Ok(func) => {
info!("Take {}.", loggable_item_name());
self.functions.push(func);
}
Err(msg) => {
error!("Cannot use fn {} ({}).", loggable_item_name(), msg);
}
match (is_extern_c, exported_name) {
(true, Some(exported_name)) => {
let path = Path::new(exported_name);
match Function::load(path, self_type, sig, false, attrs, mod_cfg) {
Ok(func) => {
info!("Take {}.", loggable_item_name());
self.functions.push(func);
}
Err(msg) => {
error!("Cannot use fn {} ({}).", loggable_item_name(), msg);
}
}
(true, None) => {
warn!(
"Skipping {} - (not `no_mangle`, and has no `export_name` attribute)",
loggable_item_name()
);
}
(false, Some(_exported_name)) => {
warn!("Skipping {} - (not `extern \"C\"`", loggable_item_name());
}
(false, None) => {}
}
} else {
match (is_extern_c, exported_name) {
(true, Some(..)) => {
warn!(
"Skipping {} - (not `pub` but is `extern \"C\"` and `no_mangle`)",
loggable_item_name()
);
}
(true, None) => {
warn!(
"Skipping {} - (not `pub` but is `extern \"C\"`)",
loggable_item_name()
);
}
(false, Some(..)) => {
warn!(
"Skipping {} - (not `pub` but is `no_mangle`)",
loggable_item_name()
);
}
(false, None) => {}
(true, None) => {
warn!(
"Skipping {} - (not `no_mangle`, and has no `export_name` attribute)",
loggable_item_name()
);
}
(false, Some(_exported_name)) => {
warn!("Skipping {} - (not `extern \"C\"`", loggable_item_name());
}
(false, None) => {}
}
}
@@ -892,27 +865,18 @@ impl Parse {
return;
}
if let syn::Visibility::Public(_) = item.vis {
if item.is_no_mangle() {
match Static::load(item, mod_cfg) {
Ok(constant) => {
info!("Take {}::{}.", crate_name, &item.ident);
self.globals.try_insert(constant);
}
Err(msg) => {
warn!("Skip {}::{} - ({})", crate_name, &item.ident, msg);
}
if let Some(exported_name) = item.exported_name() {
let path = Path::new(exported_name);
match Static::load(path, item, mod_cfg) {
Ok(constant) => {
info!("Take {}::{}.", crate_name, &item.ident);
self.globals.try_insert(constant);
}
Err(msg) => {
warn!("Skip {}::{} - ({})", crate_name, &item.ident, msg);
}
}
}
// TODO
if let syn::Visibility::Public(_) = item.vis {
} else {
warn!("Skip {}::{} - (not `pub`).", crate_name, &item.ident);
}
if !item.is_no_mangle() {
warn!("Skip {}::{} - (not `no_mangle`).", crate_name, &item.ident);
}
}
+17 -3
View File
@@ -30,11 +30,11 @@ where
}
}
pub trait SynItemFnHelpers: SynAttributeHelpers {
pub trait SynItemHelpers: SynAttributeHelpers {
fn exported_name(&self) -> Option<String>;
}
impl SynItemFnHelpers for syn::ItemFn {
impl SynItemHelpers for syn::ItemFn {
fn exported_name(&self) -> Option<String> {
self.attrs
.attr_name_value_lookup("export_name")
@@ -48,7 +48,7 @@ impl SynItemFnHelpers for syn::ItemFn {
}
}
impl SynItemFnHelpers for syn::ImplItemMethod {
impl SynItemHelpers for syn::ImplItemMethod {
fn exported_name(&self) -> Option<String> {
self.attrs
.attr_name_value_lookup("export_name")
@@ -62,6 +62,20 @@ impl SynItemFnHelpers for syn::ImplItemMethod {
}
}
impl SynItemHelpers for syn::ItemStatic {
fn exported_name(&self) -> Option<String> {
self.attrs
.attr_name_value_lookup("export_name")
.or_else(|| {
if self.is_no_mangle() {
Some(self.ident.unraw().to_string())
} else {
None
}
})
}
}
/// Returns whether this attribute causes us to skip at item. This basically
/// checks for `#[cfg(test)]`, `#[test]`, `/// cbindgen::ignore` and
/// variations thereof.
+12
View File
@@ -0,0 +1,12 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
extern const uint32_t FIRST;
extern const uint32_t RENAMED;
void first(void);
void renamed(void);
@@ -0,0 +1,20 @@
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
extern const uint32_t FIRST;
extern const uint32_t RENAMED;
void first(void);
void renamed(void);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
+17
View File
@@ -0,0 +1,17 @@
#include <cstdarg>
#include <cstdint>
#include <cstdlib>
#include <ostream>
#include <new>
extern "C" {
extern const uint32_t FIRST;
extern const uint32_t RENAMED;
void first();
void renamed();
} // extern "C"
+15
View File
@@ -0,0 +1,15 @@
from libc.stdint cimport int8_t, int16_t, int32_t, int64_t, intptr_t
from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t
cdef extern from *:
ctypedef bint bool
ctypedef struct va_list
cdef extern from *:
extern const uint32_t FIRST;
extern const uint32_t RENAMED;
void first();
void renamed();
+13
View File
@@ -0,0 +1,13 @@
#[no_mangle]
static FIRST: u32 = 10;
#[export_name = "RENAMED"]
static SECOND: u32 = 42;
#[no_mangle]
extern "C" fn first()
{ }
#[export_name = "renamed"]
extern fn second()
{ }