Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions crates/libs/rdl/src/clang/cx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,10 @@ impl Cursor {
pub fn result_type(&self) -> Type {
Type(unsafe { clang_getCursorResultType(self.0) })
}

pub fn language(&self) -> CXLanguageKind {
unsafe { clang_getCursorLanguage(self.0) }
}
}

pub struct Type(CXType);
Expand Down
17 changes: 15 additions & 2 deletions crates/libs/rdl/src/clang/fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,16 @@ pub struct Fn {
pub library: String,
pub params: Vec<Param>,
pub return_type: metadata::Type,
pub extern_c: bool,
}

impl Fn {
pub fn parse(cursor: Cursor, namespace: &str, library: &str) -> Result<Self, Error> {
pub fn parse(
cursor: Cursor,
namespace: &str,
library: &str,
extern_c: bool,
) -> Result<Self, Error> {
let name = cursor.name();
let return_type = cursor.result_type().to_type(namespace);

Expand All @@ -32,6 +38,7 @@ impl Fn {
library: library.to_string(),
params,
return_type,
extern_c,
})
}

Expand All @@ -53,9 +60,15 @@ impl Fn {
}
};

let abi = if self.extern_c {
quote! { "C" }
} else {
quote! {}
};

Ok(quote! {
#[library(#library)]
extern fn #name(#(#params),*) #return_type;
extern #abi fn #name(#(#params),*) #return_type;
})
}
}
27 changes: 26 additions & 1 deletion crates/libs/rdl/src/clang/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,32 @@ impl Clang {
}
}
CXCursor_FunctionDecl if !child.is_definition() => {
collector.insert(Item::Fn(Fn::parse(child, &self.namespace, &self.library)?));
collector.insert(Item::Fn(Fn::parse(
child,
&self.namespace,
&self.library,
false,
)?));
}
// Recurse into `extern "C" { }` or `extern "C++" { }` blocks so
// that function declarations inside them are collected with the
// correct ABI annotation.
CXCursor_LinkageSpec => {
for inner in child.children() {
if !inner.is_from_main_file() {
continue;
}
if inner.kind() == CXCursor_FunctionDecl && !inner.is_definition() {
// A function inside `extern "C" { }` has C language linkage.
let extern_c = inner.language() == CXLanguage_C;
collector.insert(Item::Fn(Fn::parse(
inner,
&self.namespace,
&self.library,
extern_c,
)?));
}
}
}
CXCursor_MacroDefinition => {
if let Some(c) = Const::parse(child, &self.namespace, tu)? {
Expand Down
6 changes: 3 additions & 3 deletions crates/tests/libs/clang/roundtrip/enum.rdl
Comment thread
riverar marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#[win32]
mod Test {
#[repr(i32)]
#[repr(u32)]
enum Name {
One = 1,
Two = 2,
}
const ONE: i32 = 1;
const TWO: i32 = 2;
const ONE: u32 = 1;
const TWO: u32 = 2;
Comment thread
riverar marked this conversation as resolved.
Outdated
}
5 changes: 5 additions & 0 deletions crates/tests/libs/clang/roundtrip/fn_extern_c.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
extern "C"
{
unsigned int GetTickCount();
void SetLastErrorEx(unsigned a, signed b);
}
7 changes: 7 additions & 0 deletions crates/tests/libs/clang/roundtrip/fn_extern_c.rdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#[win32]
mod Test {
#[library("test.dll")]
extern "C" fn GetTickCount() -> u32;
#[library("test.dll")]
extern "C" fn SetLastErrorEx(a: u32, b: i32);
}
Loading