Native interoperability library for Scala Native providing unsafe operations, C-style data types, and memory management primitives for direct interaction with native code
—
Scala Native nativelib provides comprehensive C interoperability through type aliases, string conversions, arrays, structures, function pointers, and variadic arguments for seamless integration with C libraries.
Direct mapping between Scala and C primitive types:
// Signed integer types
type CChar = Byte
type CSignedChar = Byte
type CShort = Short
type CInt = Int
type CLong = Size // Platform dependent
type CLongInt = Size
type CLongLong = Long
// Unsigned integer types
type CUnsignedChar = UByte
type CUnsignedShort = UShort
type CUnsignedInt = UInt
type CUnsignedLong = USize // Platform dependent
type CUnsignedLongLong = ULong
// Floating point types
type CFloat = Float
type CDouble = Double
// Character types
type CWideChar = UInt // C++ wchar_t
type CChar16 = UShort // C++ char16_t
type CChar32 = UInt // C++ char32_t
// Boolean and size types
type CBool = Boolean // C _Bool, C++ bool
type CSize = USize // size_t
type CSSize = Size // ssize_t
type CPtrDiff = Size // ptrdiff_t
// Pointer types
type CVoidPtr = Ptr[Byte]
type CString = Ptr[CChar]
type CWideString = Ptr[CWideChar]def fromCString(cstr: CString, charset: Charset = Charset.defaultCharset()): String
def toCString(str: String)(implicit z: Zone): CString
def toCString(str: String, charset: Charset)(implicit z: Zone): CStringString conversion functions:
fromCString(cstr, charset) - Convert null-terminated C string to Scala StringtoCString(str) - Convert Scala String to C string using default charsettoCString(str, charset) - Convert Scala String to C string with specified charsetdef fromCWideString(cwstr: CWideString, charset: Charset): String
def fromCWideString(cwstr: Ptr[CChar16], charset: Charset): String
def toCWideString(str: String, charset: Charset = StandardCharsets.UTF_16LE)(implicit z: Zone): CWideString
def toCWideStringUTF16LE(str: String)(implicit z: Zone): Ptr[CChar16]Wide string functions:
fromCWideString - Convert wide C string to Scala StringtoCWideString - Convert Scala String to wide C stringtoCWideStringUTF16LE - Convert to UTF-16 LE wide stringimplicit class CQuote(val ctx: StringContext) {
def c(): CString
}Usage: c"Hello World" creates a compile-time C string literal.
Fixed-size C-style arrays with compile-time size information:
final class CArray[T, N <: Nat] {
def length(implicit tag: Tag[N]): Int
def apply(idx: Int)(implicit tag: Tag[T]): T
def update(idx: Int, value: T)(implicit tag: Tag[T]): Unit
def at(idx: Int)(implicit tag: Tag[T]): Ptr[T]
}CArray methods:
length - Get array length (compile-time constant)apply(idx) - Read element at indexupdate(idx, value) - Write element at indexat(idx) - Get pointer to element at indexsealed abstract class Nat
object Nat {
class _0 extends Nat
class _1 extends Nat
class _2 extends Nat
class _3 extends Nat
// ... continues to higher numbers
// Digit types for building larger numbers
class Digit2[N <: Nat] extends Nat
class Digit3[N <: Nat] extends Nat
// ... up to Digit9
}Type-safe C structure representations with field access:
sealed abstract class CStruct
final class CStruct0 {
def toPtr: Ptr[CStruct0]
}
final class CStruct1[T1] extends CStruct {
def toPtr: Ptr[CStruct1[T1]]
def at1(implicit tag: Tag.CStruct1[T1]): Ptr[T1]
def _1(implicit tag: Tag.CStruct1[T1]): T1
def _1_=(value: T1)(implicit tag: Tag.CStruct1[T1]): Unit
}
final class CStruct2[T1, T2] extends CStruct {
def toPtr: Ptr[CStruct2[T1, T2]]
def at1(implicit tag: Tag.CStruct2[T1, T2]): Ptr[T1]
def at2(implicit tag: Tag.CStruct2[T1, T2]): Ptr[T2]
def _1(implicit tag: Tag.CStruct2[T1, T2]): T1
def _1_=(value: T1)(implicit tag: Tag.CStruct2[T1, T2]): Unit
def _2(implicit tag: Tag.CStruct2[T1, T2]): T2
def _2_=(value: T2)(implicit tag: Tag.CStruct2[T1, T2]): Unit
}
// Complete family: CStruct3 through CStruct22 available
// Each CStructN provides _1 through _N field access and at1 through atN pointer access
final class CStruct3[T1, T2, T3] extends CStruct {
def toPtr: Ptr[CStruct3[T1, T2, T3]]
def at1: Ptr[T1]
def at2: Ptr[T2]
def at3: Ptr[T3]
def _1: T1
def _1_=(value: T1): Unit
def _2: T2
def _2_=(value: T2): Unit
def _3: T3
def _3_=(value: T3): Unit
}
// Pattern continues: CStruct4, CStruct5, ... CStruct22
// Maximum 22 fields supported (matches Scala function arity limit)Complete CStruct Family:
CStruct0 - Empty structure (no fields)CStruct1[T1] through CStruct22[T1, T2, ..., T22] - Structures with 1-22 typed fieldsstruct._1, struct._2, etc.struct._1 = valuestruct.at1, struct.at2, etc.struct.toPtrCStruct base traitType-safe function pointers for C callbacks and native function calls:
sealed abstract class CFuncPtr
// Base function pointer companion with conversion utilities
object CFuncPtr {
def fromPtr[F <: CFuncPtr](ptr: CVoidPtr): F
def toPtr(ptr: CFuncPtr): CVoidPtr
}
// Zero-argument function pointer
final class CFuncPtr0[R] extends CFuncPtr {
def apply(): R
}
object CFuncPtr0 {
implicit def fromScalaFunction[R](fn: Function0[R]): CFuncPtr0[R]
}
// Single-argument function pointer
final class CFuncPtr1[T1, R] extends CFuncPtr {
def apply(arg1: T1): R
}
object CFuncPtr1 {
implicit def fromScalaFunction[T1, R](fn: Function1[T1, R]): CFuncPtr1[T1, R]
}
// Two-argument function pointer
final class CFuncPtr2[T1, T2, R] extends CFuncPtr {
def apply(arg1: T1, arg2: T2): R
}
object CFuncPtr2 {
implicit def fromScalaFunction[T1, T2, R](fn: Function2[T1, T2, R]): CFuncPtr2[T1, T2, R]
}
// Three-argument function pointer
final class CFuncPtr3[T1, T2, T3, R] extends CFuncPtr {
def apply(arg1: T1, arg2: T2, arg3: T3): R
}
object CFuncPtr3 {
implicit def fromScalaFunction[T1, T2, T3, R](fn: Function3[T1, T2, T3, R]): CFuncPtr3[T1, T2, T3, R]
}
// Pattern continues: CFuncPtr4 through CFuncPtr22
// Each CFuncPtrN supports N arguments with type parameters T1, T2, ..., TN, R
// All provide apply(arg1, arg2, ..., argN): R method
// All companion objects provide implicit conversion from corresponding Scala FunctionNComplete CFuncPtr Family:
CFuncPtr0[R] through CFuncPtr22[T1, T2, ..., T22, R] - Function pointers with 0-22 argumentsapply() methodFunction0 through Function22CFuncPtr companion objectFunction pointer usage:
funcPtr(arg1, arg2)val cFuncPtr: CFuncPtr2[Int, Int, Int] = (a: Int, b: Int) => a + bCFuncPtr.toPtr(funcPtr) and CFuncPtr.fromPtr[CFuncPtr1[Int, Int]](ptr)Support for C-style variadic function calls:
abstract class CVarArg
final class CVarArgList {
// Internal implementation for variadic calls
}
def toCVarArgList()(implicit z: Zone): CVarArgList
def toCVarArgList(vararg: CVarArg, varargs: CVarArg*)(implicit z: Zone): CVarArgList
def toCVarArgList(varargs: Seq[CVarArg])(implicit z: Zone): CVarArgListVariadic argument functions:
toCVarArgList() - Create empty vararg listtoCVarArgList(args...) - Create vararg list from argumentstoCVarArgList(seq) - Create vararg list from sequenceAnnotations for marking external C interface elements:
final class extern extends scala.annotation.StaticAnnotation
final class blocking extends scala.annotation.StaticAnnotation
def extern: NothingExternal annotations:
@extern - Mark objects containing external definitions@blocking - Mark methods that may block (for threading)extern - Right-hand side value for external declarationsimport scala.scalanative.unsafe._
import java.nio.charset.StandardCharsets
Zone.acquire { implicit z =>
// Convert Scala string to C string
val message = "Hello from Scala Native!"
val cstring: CString = toCString(message)
// Use with C function (hypothetical)
// puts(cstring)
// Convert back to Scala string
val recovered: String = fromCString(cstring)
// With specific charset
val utf8String: CString = toCString(message, StandardCharsets.UTF_8)
}import scala.scalanative.unsafe._
// Define array size at type level
type Array10 = CArray[CInt, Nat.Digit1[Nat._0]] // Size 10
Zone.acquire { implicit z =>
val array = alloc[Array10]
// Access like normal array
array(0) = 42
array(1) = 84
val length = array.length // Compile-time constant: 10
val value = array(0) // Read: 42
// Get pointer to element
val ptr = array.at(5)
!ptr = 123
}import scala.scalanative.unsafe._
// Define a point structure
type Point = CStruct2[CDouble, CDouble]
Zone.acquire { implicit z =>
val point = alloc[Point]
// Set coordinates
point._1 = 3.14 // x coordinate
point._2 = 2.71 // y coordinate
// Read coordinates
val x: CDouble = point._1
val y: CDouble = point._2
// Get pointers to fields
val xPtr = point.at1
val yPtr = point.at2
}import scala.scalanative.unsafe._
// C function signature: int compare(int a, int b)
type CompareFn = CFuncPtr2[CInt, CInt, CInt]
def useComparator(compareFn: CompareFn): CInt = {
// Call the function pointer
val result = compareFn(42, 24)
result
}
// Convert Scala function to function pointer
val scalaComparator: (CInt, CInt) => CInt = (a, b) => a - b
val cFuncPtr: CompareFn = scalaComparator
val result = useComparator(cFuncPtr)import scala.scalanative.unsafe._
@extern
object LibC {
// C function: int puts(const char* str)
def puts(str: CString): CInt = extern
// C function: void* malloc(size_t size)
def malloc(size: CSize): Ptr[Byte] = extern
// C function: void free(void* ptr)
def free(ptr: Ptr[Byte]): Unit = extern
// Blocking I/O function
@blocking
def read(fd: CInt, buf: Ptr[Byte], count: CSize): CSSize = extern
}
// Usage
Zone.acquire { implicit z =>
val message = toCString("Hello from C!")
LibC.puts(message)
}Install with Tessl CLI
npx tessl i tessl/maven-org-scala-native--nativelib-native0-5-3