CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-scala-native--nativelib-native0-5-3

Native interoperability library for Scala Native providing unsafe operations, C-style data types, and memory management primitives for direct interaction with native code

Pending
Overview
Eval results
Files

c-interop.mddocs/

C Interoperability

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.

C Type System

Primitive Type Aliases

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]

String Conversions

C String Functions

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): CString

String conversion functions:

  • fromCString(cstr, charset) - Convert null-terminated C string to Scala String
  • toCString(str) - Convert Scala String to C string using default charset
  • toCString(str, charset) - Convert Scala String to C string with specified charset

Wide String Functions

def 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 String
  • toCWideString - Convert Scala String to wide C string
  • toCWideStringUTF16LE - Convert to UTF-16 LE wide string

String Literal Interpolation

implicit class CQuote(val ctx: StringContext) {
  def c(): CString
}

Usage: c"Hello World" creates a compile-time C string literal.

C Arrays

CArray Type

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 index
  • update(idx, value) - Write element at index
  • at(idx) - Get pointer to element at index

Natural Numbers for Array Sizes

sealed 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
}

C Structures

Structure Types

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 fields
  • Field access: struct._1, struct._2, etc.
  • Field assignment: struct._1 = value
  • Pointer to field: struct.at1, struct.at2, etc.
  • Pointer to struct: struct.toPtr
  • All structures extend CStruct base trait

Function Pointers

Function Pointer Types

Type-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 FunctionN

Complete CFuncPtr Family:

  • CFuncPtr0[R] through CFuncPtr22[T1, T2, ..., T22, R] - Function pointers with 0-22 arguments
  • Type-safe function calls through apply() method
  • Implicit conversions from Scala functions: Function0 through Function22
  • Zero-cost abstraction over native function pointers
  • Pointer conversion utilities in CFuncPtr companion object

Function pointer usage:

  • Direct calls: funcPtr(arg1, arg2)
  • Conversion from Scala functions: val cFuncPtr: CFuncPtr2[Int, Int, Int] = (a: Int, b: Int) => a + b
  • Pointer manipulation: CFuncPtr.toPtr(funcPtr) and CFuncPtr.fromPtr[CFuncPtr1[Int, Int]](ptr)

Variadic Arguments

CVarArg Types

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): CVarArgList

Variadic argument functions:

  • toCVarArgList() - Create empty vararg list
  • toCVarArgList(args...) - Create vararg list from arguments
  • toCVarArgList(seq) - Create vararg list from sequence

External Annotations

Annotation Types

Annotations for marking external C interface elements:

final class extern extends scala.annotation.StaticAnnotation
final class blocking extends scala.annotation.StaticAnnotation

def extern: Nothing

External annotations:

  • @extern - Mark objects containing external definitions
  • @blocking - Mark methods that may block (for threading)
  • extern - Right-hand side value for external declarations

Usage Examples

Basic C String Usage

import 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)
}

C Array Usage

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
}

C Structure Usage

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
}

Function Pointer Usage

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)

External Function Declaration

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)
}

Best Practices

  1. Use Zone.acquire for automatic memory management of converted strings
  2. Specify charsets explicitly when working with non-ASCII text
  3. Check for null when receiving C strings from external functions
  4. Use appropriate structure types - match C struct layout exactly
  5. Convert function pointers carefully - ensure calling conventions match
  6. Handle variadic arguments properly - convert all arguments to CVarArg first
  7. Use @blocking annotation for functions that may block to ensure proper threading behavior

Install with Tessl CLI

npx tessl i tessl/maven-org-scala-native--nativelib-native0-5-3

docs

annotations.md

arrays-runtime.md

c-interop.md

index.md

memory-management.md

unsigned-types.md

tile.json