144 lines
3.2 KiB
Plaintext
144 lines
3.2 KiB
Plaintext
---
|
|
title: Exporting from Onyx
|
|
---
|
|
|
|
:source-highlighter: highlightjs
|
|
|
|
In Onyx, you may `export` a C entity from within an Onyx source file.
|
|
Later in the Onyx context, the entity is treated as if it was imported directly from a C header.
|
|
|
|
Unlike in raw C headers, an `export` statement is written in some mix of C with Onyx, allowing Onyx annotations, Onyx macros and having function bodies written in Onyx.
|
|
|
|
Normally, an `export` statement uses the ISO C syntax, and C vendor extensions support is undefined.
|
|
It is recommended to make use of Onyx annotations instead, which may be converted in accordance with a target vendor's semantics.
|
|
To achieve that, an Onyx implementation should maintain some sort of mapping between vendor C extensions and according Onyx semantics.
|
|
|
|
For example, FNX supports GCC extensions.
|
|
Upon generating a header file from Onyx source, the C vendor option (`-c[-w]`) is respected, and Onyx annotations are converted to the vendor's.
|
|
|
|
====
|
|
.main.nx
|
|
```
|
|
# A struct comment.
|
|
@[Pack]
|
|
export struct struct_t {
|
|
// A variable comment.
|
|
@[Align<8>]
|
|
int foo;
|
|
|
|
double bar;
|
|
};
|
|
```
|
|
|
|
After running `fnx doc -fh -c[-wgnu] main.nx`:
|
|
|
|
.main.h
|
|
```c
|
|
// A struct comment.
|
|
struct __attribute__ ((__packed__)) struct_t {
|
|
// My comment.
|
|
int foo __attribute__ ((aligned (8)));
|
|
|
|
double bar;
|
|
}
|
|
```
|
|
====
|
|
|
|
A C macro is treated as a freestanding entity, hence requiring a separate `export` entity per macro, for example:
|
|
|
|
====
|
|
.main.nx
|
|
```nx
|
|
export #ifdef __GNUC__
|
|
@[AlwaysInline]
|
|
export int foo();
|
|
export #elif _MSC_VER
|
|
@[AlwaysInline]
|
|
export double foo();
|
|
export #endif
|
|
```
|
|
|
|
After running `fnx doc -fh -c[-wgnu] main.nx`:
|
|
|
|
.main.h
|
|
```c
|
|
#ifdef __GNUC__
|
|
__attribute__((always_inline))
|
|
int foo();
|
|
#elif _MSC_VER
|
|
__attribute__((always_inline))
|
|
double foo();
|
|
#endif
|
|
```
|
|
|
|
Note that both annotations have expanded to GCC attributes regardless of the `_MSC_VER` macro, because the behaviour is controlled by the `-c[-w]` option.
|
|
To solve that, you either want to use explicit C annotations:
|
|
|
|
.main.nx
|
|
```nx
|
|
export #ifdef __GNUC__
|
|
export __attribute__((always_inline)) int foo();
|
|
export #elif _MSC_VER
|
|
export __forceinline double foo();
|
|
export #endif
|
|
```
|
|
|
|
Or expand them in macros (which is equivalent to writing them explicitly):
|
|
|
|
.main.nx
|
|
```nx
|
|
macro attr(vendor)
|
|
{{ nx.id["AlwaysInline"]:c(vendor) }}
|
|
end
|
|
|
|
export #ifdef __GNUC__
|
|
export @attr("gnu") int foo();
|
|
export #elif _MSC_VER
|
|
export @attr("msvc") double foo();
|
|
export #endif
|
|
```
|
|
====
|
|
|
|
Sometimes it may become cumbersome to have a separate `export` statement per entity, like in the examples above.
|
|
To deal with that, Onyx allows to export entire blocks in the same C-NX syntax.
|
|
The same rules apply.
|
|
|
|
====
|
|
.main.nx
|
|
```nx
|
|
export {
|
|
#ifdef __GNUC__
|
|
@[AlwaysInline]
|
|
int foo();
|
|
#elif _MSC_VER
|
|
@[AlwaysInline]
|
|
double foo();
|
|
#endif
|
|
|
|
// A C comment
|
|
@[NoInline]
|
|
void main() {
|
|
# Some Onyx code
|
|
}
|
|
}
|
|
```
|
|
|
|
After running `fnx doc -fh -c[-wgnu] main.nx`:
|
|
|
|
.main.h
|
|
```c
|
|
#ifdef __GNUC__
|
|
__attribute__((always_inline))
|
|
int foo();
|
|
#elif _MSC_VER
|
|
__attribute__((always_inline))
|
|
double foo();
|
|
#endif
|
|
|
|
// A C comment
|
|
void main() __attribute__((noinline));
|
|
```
|
|
====
|
|
|
|
It is common to have entire files written in this manner when tight interoperability with C is implied, usually with an `.cnx` extension.
|