Repository: mozilla/cbindgen (language: rust)

Issue:
Extern "C" functions being re-exported
We have an application that is part Rust, part C.  We use `extern "C" {` to define C functions to Rust. However, `cbindgen` appears to re-export these back out. Short of listing all these in the exclude list, can they still be ignored?

We still want to export Rust functions that are declared extern so our C code can bind to them.

Note: When just `extern {` is used these C functions are not re-exported, but we'd like to use as many `rustfmt` defaults as possible, which rewrites these to `extern "C"`.


Discussion / hints:
Can you annotate them on the source with `/// cbindgen:ignore`?
Comment `/// cbindgen:ignore` actually works but it would be nice to ignore those by default.
> Can you annotate them on the source with `/// cbindgen:ignore`?

This works on the module level, but not just on an `extern "C" {}` block which would be more useful.

I think the bigger question is why `extern "C" {}` and `extern {}` are treated differently by cbindgen?  And why export functions defined this way anyways, presumably they're in a C header already.  Our use case is to create C bindings for a C app to use our Rust code.  We don't need cbindgen to re-export definitions of extern functions.

Happy to look at a fix if there is not a specific reason for the current behaviour.


Fix patch:
diff --git a/src/bindgen/parser.rs b/src/bindgen/parser.rs
index ddc3672a8..c418e9d2a 100644
--- a/src/bindgen/parser.rs
+++ b/src/bindgen/parser.rs
@@ -600,7 +600,7 @@ impl Parse {
         mod_cfg: Option<&Cfg>,
         item: &syn::ItemForeignMod,
     ) {
-        if !item.abi.is_c() {
+        if !item.abi.is_c() && !item.abi.is_omitted() {
             info!("Skip {} - (extern block must be extern C).", crate_name);
             return;
         }


Test patch:
diff --git a/tests/expectations/extern.c b/tests/expectations/extern.c
index 6fe9f5bdb..70b2a3be9 100644
--- a/tests/expectations/extern.c
+++ b/tests/expectations/extern.c
@@ -11,3 +11,5 @@ typedef struct {
 extern int32_t foo(void);
 
 extern void bar(Normal a);
+
+extern int32_t baz(void);
diff --git a/tests/expectations/extern.compat.c b/tests/expectations/extern.compat.c
index 4f4129ad5..7cf348439 100644
--- a/tests/expectations/extern.compat.c
+++ b/tests/expectations/extern.compat.c
@@ -16,6 +16,8 @@ extern int32_t foo(void);
 
 extern void bar(Normal a);
 
+extern int32_t baz(void);
+
 #ifdef __cplusplus
 } // extern "C"
 #endif // __cplusplus
diff --git a/tests/expectations/extern.cpp b/tests/expectations/extern.cpp
index 15294c05c..ecdea3c11 100644
--- a/tests/expectations/extern.cpp
+++ b/tests/expectations/extern.cpp
@@ -15,4 +15,6 @@ extern int32_t foo();
 
 extern void bar(Normal a);
 
+extern int32_t baz();
+
 } // extern "C"
diff --git a/tests/expectations/extern.pyx b/tests/expectations/extern.pyx
index dca17ac8f..51b05833c 100644
--- a/tests/expectations/extern.pyx
+++ b/tests/expectations/extern.pyx
@@ -13,3 +13,5 @@ cdef extern from *:
   extern int32_t foo();
 
   extern void bar(Normal a);
+
+  extern int32_t baz();
diff --git a/tests/expectations/extern_both.c b/tests/expectations/extern_both.c
index 026661a64..56aad04ef 100644
--- a/tests/expectations/extern_both.c
+++ b/tests/expectations/extern_both.c
@@ -11,3 +11,5 @@ typedef struct Normal {
 extern int32_t foo(void);
 
 extern void bar(struct Normal a);
+
+extern int32_t baz(void);
diff --git a/tests/expectations/extern_both.compat.c b/tests/expectations/extern_both.compat.c
index 3c49da31e..dff58551d 100644
--- a/tests/expectations/extern_both.compat.c
+++ b/tests/expectations/extern_both.compat.c
@@ -16,6 +16,8 @@ extern int32_t foo(void);
 
 extern void bar(struct Normal a);
 
+extern int32_t baz(void);
+
 #ifdef __cplusplus
 } // extern "C"
 #endif // __cplusplus
diff --git a/tests/expectations/extern_tag.c b/tests/expectations/extern_tag.c
index 5a88d1a22..e70c271a2 100644
--- a/tests/expectations/extern_tag.c
+++ b/tests/expectations/extern_tag.c
@@ -11,3 +11,5 @@ struct Normal {
 extern int32_t foo(void);
 
 extern void bar(struct Normal a);
+
+extern int32_t baz(void);
diff --git a/tests/expectations/extern_tag.compat.c b/tests/expectations/extern_tag.compat.c
index 3ca162513..a2d9ea961 100644
--- a/tests/expectations/extern_tag.compat.c
+++ b/tests/expectations/extern_tag.compat.c
@@ -16,6 +16,8 @@ extern int32_t foo(void);
 
 extern void bar(struct Normal a);
 
+extern int32_t baz(void);
+
 #ifdef __cplusplus
 } // extern "C"
 #endif // __cplusplus
diff --git a/tests/expectations/extern_tag.pyx b/tests/expectations/extern_tag.pyx
index 9cb7214a4..f62773325 100644
--- a/tests/expectations/extern_tag.pyx
+++ b/tests/expectations/extern_tag.pyx
@@ -13,3 +13,5 @@ cdef extern from *:
   extern int32_t foo();
 
   extern void bar(Normal a);
+
+  extern int32_t baz();
diff --git a/tests/rust/extern.rs b/tests/rust/extern.rs
index 3bd83d17f..e9a93920e 100644
--- a/tests/rust/extern.rs
+++ b/tests/rust/extern.rs
@@ -9,3 +9,7 @@ extern "C" {
 
     fn bar(a: Normal);
 }
+
+extern {
+    fn baz() -> i32;
+}