or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

annotations.mdarrays-runtime.mdc-interop.mdindex.mdmemory-management.mdunsigned-types.md

c-interop.mddocs/

0

# C Interoperability

1

2

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.

3

4

## C Type System

5

6

### Primitive Type Aliases

7

8

Direct mapping between Scala and C primitive types:

9

10

```scala { .api }

11

// Signed integer types

12

type CChar = Byte

13

type CSignedChar = Byte

14

type CShort = Short

15

type CInt = Int

16

type CLong = Size // Platform dependent

17

type CLongInt = Size

18

type CLongLong = Long

19

20

// Unsigned integer types

21

type CUnsignedChar = UByte

22

type CUnsignedShort = UShort

23

type CUnsignedInt = UInt

24

type CUnsignedLong = USize // Platform dependent

25

type CUnsignedLongLong = ULong

26

27

// Floating point types

28

type CFloat = Float

29

type CDouble = Double

30

31

// Character types

32

type CWideChar = UInt // C++ wchar_t

33

type CChar16 = UShort // C++ char16_t

34

type CChar32 = UInt // C++ char32_t

35

36

// Boolean and size types

37

type CBool = Boolean // C _Bool, C++ bool

38

type CSize = USize // size_t

39

type CSSize = Size // ssize_t

40

type CPtrDiff = Size // ptrdiff_t

41

42

// Pointer types

43

type CVoidPtr = Ptr[Byte]

44

type CString = Ptr[CChar]

45

type CWideString = Ptr[CWideChar]

46

```

47

48

## String Conversions

49

50

### C String Functions

51

52

```scala { .api }

53

def fromCString(cstr: CString, charset: Charset = Charset.defaultCharset()): String

54

def toCString(str: String)(implicit z: Zone): CString

55

def toCString(str: String, charset: Charset)(implicit z: Zone): CString

56

```

57

58

**String conversion functions**:

59

- `fromCString(cstr, charset)` - Convert null-terminated C string to Scala String

60

- `toCString(str)` - Convert Scala String to C string using default charset

61

- `toCString(str, charset)` - Convert Scala String to C string with specified charset

62

63

### Wide String Functions

64

65

```scala { .api }

66

def fromCWideString(cwstr: CWideString, charset: Charset): String

67

def fromCWideString(cwstr: Ptr[CChar16], charset: Charset): String

68

def toCWideString(str: String, charset: Charset = StandardCharsets.UTF_16LE)(implicit z: Zone): CWideString

69

def toCWideStringUTF16LE(str: String)(implicit z: Zone): Ptr[CChar16]

70

```

71

72

**Wide string functions**:

73

- `fromCWideString` - Convert wide C string to Scala String

74

- `toCWideString` - Convert Scala String to wide C string

75

- `toCWideStringUTF16LE` - Convert to UTF-16 LE wide string

76

77

### String Literal Interpolation

78

79

```scala { .api }

80

implicit class CQuote(val ctx: StringContext) {

81

def c(): CString

82

}

83

```

84

85

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

86

87

## C Arrays

88

89

### CArray Type

90

91

Fixed-size C-style arrays with compile-time size information:

92

93

```scala { .api }

94

final class CArray[T, N <: Nat] {

95

def length(implicit tag: Tag[N]): Int

96

def apply(idx: Int)(implicit tag: Tag[T]): T

97

def update(idx: Int, value: T)(implicit tag: Tag[T]): Unit

98

def at(idx: Int)(implicit tag: Tag[T]): Ptr[T]

99

}

100

```

101

102

**CArray methods**:

103

- `length` - Get array length (compile-time constant)

104

- `apply(idx)` - Read element at index

105

- `update(idx, value)` - Write element at index

106

- `at(idx)` - Get pointer to element at index

107

108

### Natural Numbers for Array Sizes

109

110

```scala { .api }

111

sealed abstract class Nat

112

113

object Nat {

114

class _0 extends Nat

115

class _1 extends Nat

116

class _2 extends Nat

117

class _3 extends Nat

118

// ... continues to higher numbers

119

120

// Digit types for building larger numbers

121

class Digit2[N <: Nat] extends Nat

122

class Digit3[N <: Nat] extends Nat

123

// ... up to Digit9

124

}

125

```

126

127

## C Structures

128

129

### Structure Types

130

131

Type-safe C structure representations with field access:

132

133

```scala { .api }

134

sealed abstract class CStruct

135

136

final class CStruct0 {

137

def toPtr: Ptr[CStruct0]

138

}

139

140

final class CStruct1[T1] extends CStruct {

141

def toPtr: Ptr[CStruct1[T1]]

142

def at1(implicit tag: Tag.CStruct1[T1]): Ptr[T1]

143

def _1(implicit tag: Tag.CStruct1[T1]): T1

144

def _1_=(value: T1)(implicit tag: Tag.CStruct1[T1]): Unit

145

}

146

147

final class CStruct2[T1, T2] extends CStruct {

148

def toPtr: Ptr[CStruct2[T1, T2]]

149

def at1(implicit tag: Tag.CStruct2[T1, T2]): Ptr[T1]

150

def at2(implicit tag: Tag.CStruct2[T1, T2]): Ptr[T2]

151

def _1(implicit tag: Tag.CStruct2[T1, T2]): T1

152

def _1_=(value: T1)(implicit tag: Tag.CStruct2[T1, T2]): Unit

153

def _2(implicit tag: Tag.CStruct2[T1, T2]): T2

154

def _2_=(value: T2)(implicit tag: Tag.CStruct2[T1, T2]): Unit

155

}

156

157

// Complete family: CStruct3 through CStruct22 available

158

// Each CStructN provides _1 through _N field access and at1 through atN pointer access

159

160

final class CStruct3[T1, T2, T3] extends CStruct {

161

def toPtr: Ptr[CStruct3[T1, T2, T3]]

162

def at1: Ptr[T1]

163

def at2: Ptr[T2]

164

def at3: Ptr[T3]

165

def _1: T1

166

def _1_=(value: T1): Unit

167

def _2: T2

168

def _2_=(value: T2): Unit

169

def _3: T3

170

def _3_=(value: T3): Unit

171

}

172

173

// Pattern continues: CStruct4, CStruct5, ... CStruct22

174

// Maximum 22 fields supported (matches Scala function arity limit)

175

```

176

177

**Complete CStruct Family**:

178

- `CStruct0` - Empty structure (no fields)

179

- `CStruct1[T1]` through `CStruct22[T1, T2, ..., T22]` - Structures with 1-22 typed fields

180

- Field access: `struct._1`, `struct._2`, etc.

181

- Field assignment: `struct._1 = value`

182

- Pointer to field: `struct.at1`, `struct.at2`, etc.

183

- Pointer to struct: `struct.toPtr`

184

- All structures extend `CStruct` base trait

185

186

## Function Pointers

187

188

### Function Pointer Types

189

190

Type-safe function pointers for C callbacks and native function calls:

191

192

```scala { .api }

193

sealed abstract class CFuncPtr

194

195

// Base function pointer companion with conversion utilities

196

object CFuncPtr {

197

def fromPtr[F <: CFuncPtr](ptr: CVoidPtr): F

198

def toPtr(ptr: CFuncPtr): CVoidPtr

199

}

200

201

// Zero-argument function pointer

202

final class CFuncPtr0[R] extends CFuncPtr {

203

def apply(): R

204

}

205

206

object CFuncPtr0 {

207

implicit def fromScalaFunction[R](fn: Function0[R]): CFuncPtr0[R]

208

}

209

210

// Single-argument function pointer

211

final class CFuncPtr1[T1, R] extends CFuncPtr {

212

def apply(arg1: T1): R

213

}

214

215

object CFuncPtr1 {

216

implicit def fromScalaFunction[T1, R](fn: Function1[T1, R]): CFuncPtr1[T1, R]

217

}

218

219

// Two-argument function pointer

220

final class CFuncPtr2[T1, T2, R] extends CFuncPtr {

221

def apply(arg1: T1, arg2: T2): R

222

}

223

224

object CFuncPtr2 {

225

implicit def fromScalaFunction[T1, T2, R](fn: Function2[T1, T2, R]): CFuncPtr2[T1, T2, R]

226

}

227

228

// Three-argument function pointer

229

final class CFuncPtr3[T1, T2, T3, R] extends CFuncPtr {

230

def apply(arg1: T1, arg2: T2, arg3: T3): R

231

}

232

233

object CFuncPtr3 {

234

implicit def fromScalaFunction[T1, T2, T3, R](fn: Function3[T1, T2, T3, R]): CFuncPtr3[T1, T2, T3, R]

235

}

236

237

// Pattern continues: CFuncPtr4 through CFuncPtr22

238

// Each CFuncPtrN supports N arguments with type parameters T1, T2, ..., TN, R

239

// All provide apply(arg1, arg2, ..., argN): R method

240

// All companion objects provide implicit conversion from corresponding Scala FunctionN

241

```

242

243

**Complete CFuncPtr Family**:

244

- `CFuncPtr0[R]` through `CFuncPtr22[T1, T2, ..., T22, R]` - Function pointers with 0-22 arguments

245

- Type-safe function calls through `apply()` method

246

- Implicit conversions from Scala functions: `Function0` through `Function22`

247

- Zero-cost abstraction over native function pointers

248

- Pointer conversion utilities in `CFuncPtr` companion object

249

250

**Function pointer usage**:

251

- Direct calls: `funcPtr(arg1, arg2)`

252

- Conversion from Scala functions: `val cFuncPtr: CFuncPtr2[Int, Int, Int] = (a: Int, b: Int) => a + b`

253

- Pointer manipulation: `CFuncPtr.toPtr(funcPtr)` and `CFuncPtr.fromPtr[CFuncPtr1[Int, Int]](ptr)`

254

255

## Variadic Arguments

256

257

### CVarArg Types

258

259

Support for C-style variadic function calls:

260

261

```scala { .api }

262

abstract class CVarArg

263

264

final class CVarArgList {

265

// Internal implementation for variadic calls

266

}

267

268

def toCVarArgList()(implicit z: Zone): CVarArgList

269

def toCVarArgList(vararg: CVarArg, varargs: CVarArg*)(implicit z: Zone): CVarArgList

270

def toCVarArgList(varargs: Seq[CVarArg])(implicit z: Zone): CVarArgList

271

```

272

273

**Variadic argument functions**:

274

- `toCVarArgList()` - Create empty vararg list

275

- `toCVarArgList(args...)` - Create vararg list from arguments

276

- `toCVarArgList(seq)` - Create vararg list from sequence

277

278

## External Annotations

279

280

### Annotation Types

281

282

Annotations for marking external C interface elements:

283

284

```scala { .api }

285

final class extern extends scala.annotation.StaticAnnotation

286

final class blocking extends scala.annotation.StaticAnnotation

287

288

def extern: Nothing

289

```

290

291

**External annotations**:

292

- `@extern` - Mark objects containing external definitions

293

- `@blocking` - Mark methods that may block (for threading)

294

- `extern` - Right-hand side value for external declarations

295

296

## Usage Examples

297

298

### Basic C String Usage

299

300

```scala

301

import scala.scalanative.unsafe._

302

import java.nio.charset.StandardCharsets

303

304

Zone.acquire { implicit z =>

305

// Convert Scala string to C string

306

val message = "Hello from Scala Native!"

307

val cstring: CString = toCString(message)

308

309

// Use with C function (hypothetical)

310

// puts(cstring)

311

312

// Convert back to Scala string

313

val recovered: String = fromCString(cstring)

314

315

// With specific charset

316

val utf8String: CString = toCString(message, StandardCharsets.UTF_8)

317

}

318

```

319

320

### C Array Usage

321

322

```scala

323

import scala.scalanative.unsafe._

324

325

// Define array size at type level

326

type Array10 = CArray[CInt, Nat.Digit1[Nat._0]] // Size 10

327

328

Zone.acquire { implicit z =>

329

val array = alloc[Array10]

330

331

// Access like normal array

332

array(0) = 42

333

array(1) = 84

334

335

val length = array.length // Compile-time constant: 10

336

val value = array(0) // Read: 42

337

338

// Get pointer to element

339

val ptr = array.at(5)

340

!ptr = 123

341

}

342

```

343

344

### C Structure Usage

345

346

```scala

347

import scala.scalanative.unsafe._

348

349

// Define a point structure

350

type Point = CStruct2[CDouble, CDouble]

351

352

Zone.acquire { implicit z =>

353

val point = alloc[Point]

354

355

// Set coordinates

356

point._1 = 3.14 // x coordinate

357

point._2 = 2.71 // y coordinate

358

359

// Read coordinates

360

val x: CDouble = point._1

361

val y: CDouble = point._2

362

363

// Get pointers to fields

364

val xPtr = point.at1

365

val yPtr = point.at2

366

}

367

```

368

369

### Function Pointer Usage

370

371

```scala

372

import scala.scalanative.unsafe._

373

374

// C function signature: int compare(int a, int b)

375

type CompareFn = CFuncPtr2[CInt, CInt, CInt]

376

377

def useComparator(compareFn: CompareFn): CInt = {

378

// Call the function pointer

379

val result = compareFn(42, 24)

380

result

381

}

382

383

// Convert Scala function to function pointer

384

val scalaComparator: (CInt, CInt) => CInt = (a, b) => a - b

385

val cFuncPtr: CompareFn = scalaComparator

386

387

val result = useComparator(cFuncPtr)

388

```

389

390

### External Function Declaration

391

392

```scala

393

import scala.scalanative.unsafe._

394

395

@extern

396

object LibC {

397

// C function: int puts(const char* str)

398

def puts(str: CString): CInt = extern

399

400

// C function: void* malloc(size_t size)

401

def malloc(size: CSize): Ptr[Byte] = extern

402

403

// C function: void free(void* ptr)

404

def free(ptr: Ptr[Byte]): Unit = extern

405

406

// Blocking I/O function

407

@blocking

408

def read(fd: CInt, buf: Ptr[Byte], count: CSize): CSSize = extern

409

}

410

411

// Usage

412

Zone.acquire { implicit z =>

413

val message = toCString("Hello from C!")

414

LibC.puts(message)

415

}

416

```

417

418

## Best Practices

419

420

1. **Use Zone.acquire** for automatic memory management of converted strings

421

2. **Specify charsets explicitly** when working with non-ASCII text

422

3. **Check for null** when receiving C strings from external functions

423

4. **Use appropriate structure types** - match C struct layout exactly

424

5. **Convert function pointers carefully** - ensure calling conventions match

425

6. **Handle variadic arguments properly** - convert all arguments to CVarArg first

426

7. **Use @blocking annotation** for functions that may block to ensure proper threading behavior