docs(ffi-linkage): document extern/export linkage keywords (Phase 4)
This commit is contained in:
12
readme.md
12
readme.md
@@ -409,6 +409,18 @@ printf :: (fmt: [:0]u8, args: ..Any) -> i32 #foreign libc;
|
||||
write_fd :: (fd: i32, buf: [*]u8, count: u64) -> i64 #foreign libc "write";
|
||||
```
|
||||
|
||||
`extern` / `export` are the keyword surface for C linkage. `extern` is the modern
|
||||
spelling of `#foreign` (import); `export` is its dual — define a function in sx and
|
||||
expose it under the C ABI so C can call back in. Both imply `callconv(.c)` and take
|
||||
the same optional `[LIB] ["csym"]` rename tail; they also apply to data globals and
|
||||
to Obj-C / JNI runtime-class aggregates (postfix after the `#objc_class(…)` directive).
|
||||
```sx
|
||||
abs :: (x: i32) -> i32 extern; // import (== `#foreign`)
|
||||
sx_square :: (x: i32) -> i32 export { x * x } // define + expose to C
|
||||
__stdinp : *void extern; // extern data global
|
||||
NSObject :: #objc_class("NSObject") extern { alloc :: () -> *NSObject; } // reference a runtime class
|
||||
```
|
||||
|
||||
Direct C header import:
|
||||
```sx
|
||||
#import c {
|
||||
|
||||
34
specs.md
34
specs.md
@@ -1209,6 +1209,40 @@ write_fd :: (fd: i32, buf: [*]u8, count: u64) -> i64 #foreign libc "write";
|
||||
- `#foreign lib_ref` declares a function as external C. The library reference is optional: when present it is passed to the linker (`-lname` on Unix); when omitted (`name :: (…) -> T #foreign;`), the symbol must resolve at link time from a framework or an already-linked / auto-detected library.
|
||||
- `#foreign lib_ref "c_symbol"` renames the binding: the sx function name differs from the C symbol. This avoids name collisions (e.g. POSIX `write` vs an sx builtin).
|
||||
|
||||
#### `extern` / `export` linkage keywords
|
||||
|
||||
`extern` and `export` are the keyword surface for C linkage. `extern` is the
|
||||
modern spelling of `#foreign` (import a symbol defined elsewhere); `export` is
|
||||
its dual — **define** a symbol in sx and expose it under the C ABI so C (or asm,
|
||||
or another language) can call it. Both imply `callconv(.c)`, carry external
|
||||
linkage, and suppress the implicit sx context parameter. They are postfix
|
||||
modifiers, written where `callconv` would go.
|
||||
|
||||
```sx
|
||||
// Functions — `extern` imports, `export` defines + exposes
|
||||
abs :: (x: i32) -> i32 extern; // import (== `#foreign`)
|
||||
write_fd :: (fd: i32, buf: [*]u8, n: u64) -> i64 extern libc "write"; // [LIB] ["csym"]
|
||||
sx_square :: (x: i32) -> i32 export { x * x } // define; C can call `sx_square`
|
||||
triple_c :: (x: i32) -> i32 export "triple_c" { x * 3 } // export under a C name
|
||||
|
||||
// Data globals — `extern` imports an external global
|
||||
__stdinp : *void extern; // (== `<name> : <type> #foreign;`)
|
||||
|
||||
// Aggregates (Obj-C / JNI runtime classes) — postfix after the directive
|
||||
NSObject :: #objc_class("NSObject") extern { alloc :: () -> *NSObject; } // reference
|
||||
SxFoo :: #objc_class("SxFoo") export { counter: i32; bump :: (self: *Self) { … } } // define
|
||||
```
|
||||
|
||||
- `extern` takes the same optional `[LIB] ["csym"]` tail as `#foreign`
|
||||
(`extern libc "write"`): a `#library` alias reference then a C symbol rename.
|
||||
The `#library` declaration + build-flag linking mechanism is a separate axis —
|
||||
`extern` *references* a library, it does not declare one.
|
||||
- `export "csym"` renames the exported symbol the same way (the C-visible name
|
||||
differs from the sx name).
|
||||
- On an aggregate, the prefix `#foreign` modifier and a postfix `extern`/`export`
|
||||
keyword are the same axis and cannot be combined: `#objc_class("X") extern` is
|
||||
exactly `#foreign #objc_class("X")`; writing both is a compile error.
|
||||
|
||||
### C Interop Type Mapping
|
||||
|
||||
| C type | sx type | Notes |
|
||||
|
||||
Reference in New Issue
Block a user