Most application code can stay within safe BASIL libraries. A native interface is useful for an existing C library, a platform operation or a carefully reviewed performance boundary. It also introduces obligations that static BASIL checks cannot establish for arbitrary foreign code.
Separate the C ABI from BASIL values
EXTERN imports supported scalar C signatures from objects/archives; EXPORT emits C wrappers. The C ABI is the platform’s calling convention and representation agreement. BASIL’s internal ABI includes its own value/ownership/error contracts. Do not pass a BASIL record or string header to a C function merely because its bytes appear convenient.
Raw C interfaces support the documented scalar subset, not arbitrary structs, varargs, BYREF aggregates or fallible C signatures. BOOLEAN/C _Bool differs from C int and GObject gboolean. A reviewed adapter performs those conversions. The native adapter example builds a complete C producer, generated bridge and safe BASIL wrapper.
Pointers and unsafe authority
POINTER is a non-owning address, distinct from INTEGER. It neither frees storage nor proves that storage is valid. NullPointer and IsNullPointer are safe; reading or converting an address requires an explicit unsafe block.
pointer = NullPointer()
PRINT IsNullPointer(pointer)
UNSAFE
PRINT PointerAddress(pointer)
END UNSAFEThis example only inspects a null address. Dereferencing it would be invalid. PointerFromInteger does not create valid storage. Peek/Poke require the caller to establish readable/writable initialized memory, alignment/representation and the absence of conflicting accesses. A pointer does not extend its target’s lifetime.
UNSAFE grants specific foreign capabilities; it does not disable type, definite initialization, borrowing or checked-failure rules. An UNSAFE FUNCTION imposes caller obligations but still needs explicit unsafe blocks for its own operations. Unsafe Main and conversion of unsafe functions to safe delegates are rejected.
Callbacks across native frames
CALLBACK describes a generated noncapturing C ABI entry. Its target must be infallible and nonsuspending, cannot start tasks, and cannot allow cancellation to unwind across C. It is passed to C; it is not an ordinary BASIL callable you invoke directly. The current scalar C adapter accepts at most six parameters.
CALLABLE NOSUSPEND retains the BASIL ABI for reviewed adapters. It can have checked BASIL failures, but still cannot suspend, cancel or start tasks transitively. Neither kind captures locals. Foreign-thread entry is rejected rather than automatically attaching a new thread to BASIL. For ordinary GUI applications, queued events avoid placing application code on a native callback stack.
Publish a safe wrapper
A wrapper should own the foreign handle, hide its representation with OPAQUE TYPE, validate lengths and kinds, and expose borrowed access or explicit ownership transfer. Native code must not retain a borrowed BASIL buffer after return or suspend behind the runtime’s back. Converting a foreign address to POINTER does not make retention safe.
The versioned basic_ffi_v1.h helpers provide checked UTF-8/packed BYTE construction,
matching destruction, supported owned results and rich native errors. The adapter
generator declares borrowing, placement, return ownership and local error tags.
The GTK extension helpers similarly type-check native GObjects instead of exposing
private handle layouts. Follow the adapter reference
and its executable example when building a new binding.
Distribute compiled libraries
Use a library project and .blib when consumers are BASIL programs. Use the documented object/archive and C wrappers for a C host; these are different products. Package interfaces preserve failures, callback contracts, ownership, cleanup hooks and suspension effects. The current toolchain preserves checked ownership contracts for native resources and containers. Native File owners, resource records, lists, optionals, dictionary values and arrays can cross compatible BASIL library boundaries with the same borrows and explicit transfers as source calls. Generic templates are checked under consumer types. ABI v15 adds Display and embedded-value support while consuming supported v14 packages. Older readers reject v15 output; rebuild or upgrade with a compatible compiler/SDK when requested by diagnostics.
Save this source module as storage.bas beside its entry:
PUBLIC FUNCTION OpenInput() AS File FAILS IoError
RETURN OpenFile("/dev/null")
END FUNCTION
PUBLIC FUNCTION Size(input AS File) AS INTEGER FAILS IoError
RETURN GetFileInfo(input).Size
END FUNCTION
PUBLIC SUB Consume(TAKE input AS File) FAILS IoError
PRINT GetFileInfo(input).Size
END SUBIMPORT "storage.bas" AS storage
input = storage.OpenInput()
PRINT storage.Size(input)
storage.Consume(TAKE input)The book checks this source-import example. To distribute these declarations, build a library-manifest .blib and select it through a consumer dependency alias as in chapter 12. The package regression suite separately checks source/relocated prebuilt equivalence after removing producer sources. Consumers validate passing modes, borrow origins, effects and cleanup contracts before emitting calls. Missing/mismatched metadata produces a rebuild diagnostic.
Imported BORROW results protect every possible origin through suspension; owned returns transfer one owner. BYVAL and TAKE resource arguments need fresh or explicitly moved owners. Tasks retain their normal cleanup and Join rules. Resource keys/sets, escaping channel owners and raw C resource passing remain unsupported. Compatibility metadata does not authenticate arbitrary foreign machine code. See compiled resource contracts .
Static native inputs must use supported ELF/archive forms. A declared system-library dependency uses the hosted linker bridge and matching SDK. TLS, constructors, IFUNC and arbitrary runtime assumptions are not automatically handled by the integrated freestanding linker. Keep notices/licenses with distributed inputs.
This chapter introduces the trust boundary; it does not replace the foreign-interface contract , compiler ABI reference or binding-specific review.