Skip to content

Commit

Permalink
Support #[export_name = "..."]
Browse files Browse the repository at this point in the history
  • Loading branch information
hadashiA committed Jan 4, 2024
1 parent 2c57dce commit 402654c
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 6 deletions.
3 changes: 3 additions & 0 deletions csbindgen/src/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ pub fn emit_csharp(
let mut method_list_string = String::new();
for item in methods {
let mut method_name = &item.method_name;
if let ExportSymbolNaming::ExportName(export_name) = &item.symbol_style {
method_name = export_name;
}
let method_name_temp: String;
if method_prefix.is_empty() {
method_name_temp = escape_name(method_name);
Expand Down
40 changes: 34 additions & 6 deletions csbindgen/src/parser.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{alias_map::AliasMap, builder::BindgenOptions, field_map::FieldMap, type_meta::*};
use regex::Regex;
use std::collections::HashSet;
use syn::{ForeignItem, Item, Pat, ReturnType};
use syn::{ForeignItem, Ident, Item, Meta, MetaNameValue, Pat, ReturnType};

enum FnItem {
ForeignItem(syn::ForeignItemFn),
Expand Down Expand Up @@ -56,8 +56,8 @@ pub fn collect_extern_method(
) {
for item in depth_first_module_walk(&ast.items) {
if let Item::Fn(m) = item {
if m.sig.abi.is_some() {
// has extern
// has extern "C"
if m.sig.abi.as_ref().and_then(|x| x.name.as_ref()).filter(|x| x.value() == "C").is_some() {
let method = parse_method(FnItem::Item(m.clone()), options);
if let Some(x) = method {
list.push(x);
Expand All @@ -68,9 +68,9 @@ pub fn collect_extern_method(
}

fn parse_method(item: FnItem, options: &BindgenOptions) -> Option<ExternMethod> {
let (sig, attrs) = match item {
FnItem::ForeignItem(x) => (x.sig, x.attrs),
FnItem::Item(x) => (x.sig, x.attrs),
let (sig, attrs, is_foreign_item) = match item {
FnItem::ForeignItem(x) => (x.sig, x.attrs, true),
FnItem::Item(x) => (x.sig, x.attrs, false),
};

let method_name = sig.ident.to_string();
Expand Down Expand Up @@ -114,6 +114,33 @@ fn parse_method(item: FnItem, options: &BindgenOptions) -> Option<ExternMethod>
return_type = Some(rust_type);
}

// check attrs
let mut symbol_style = ExportSymbolNaming::NoMangle;
if (!is_foreign_item) {
let found_style = attrs.iter()
.map(|attr| {
let name = &attr.path.segments.last().unwrap().ident;
if (name == "no_mangle") {
return Some(ExportSymbolNaming::NoMangle)
} else if (name == "export_name") {
if let Ok(Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(x), .. })) = attr.parse_meta() {
return Some(ExportSymbolNaming::ExportName(x.value()));
}
}
None
})
.find(|x| x.is_some());

if (found_style.is_none()) {
println!(
"csbindgen can't handle this function because there is neither #[no_mangle] nor #[export_name] so ignore generate, method_name: {}",
method_name
);
return None;
}
symbol_style = found_style.unwrap().unwrap();
}

// doc
let doc_comment = attrs
.iter()
Expand All @@ -124,6 +151,7 @@ fn parse_method(item: FnItem, options: &BindgenOptions) -> Option<ExternMethod>
if !method_name.is_empty() && (options.method_filter)(method_name.clone()) {
return Some(ExternMethod {
method_name,
symbol_style,
parameters,
return_type,
doc_comment,
Expand Down
7 changes: 7 additions & 0 deletions csbindgen/src/type_meta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,18 @@ pub struct FieldMember {
#[derive(Clone, Debug)]
pub struct ExternMethod {
pub method_name: String,
pub symbol_style: ExportSymbolNaming,
pub doc_comment: Vec<String>,
pub parameters: Vec<Parameter>,
pub return_type: Option<RustType>,
}

#[derive(Clone, Debug)]
pub enum ExportSymbolNaming {
NoMangle,
ExportName(String)
}

impl ExternMethod {
pub fn escape_doc_comment(&self) -> Option<String> {
if self.doc_comment.is_empty() {
Expand Down

0 comments on commit 402654c

Please sign in to comment.