0
# Annotations
1
2
Scala Native provides specialized annotations for optimization control, memory layout, and external interface declarations to fine-tune native code generation and interoperability.
3
4
## Optimization Annotations
5
6
### Inlining Control
7
8
```scala { .api }
9
class alwaysinline extends scala.annotation.StaticAnnotation
10
class noinline extends scala.annotation.StaticAnnotation
11
class nooptimize extends scala.annotation.StaticAnnotation
12
class nospecialize extends scala.annotation.StaticAnnotation
13
```
14
15
**Optimization annotations**:
16
- `@alwaysinline` - Force method inlining even in debug mode
17
- `@noinline` - Prevent method from being inlined
18
- `@nooptimize` - Disable all optimizations (implies noinline and nospecialize)
19
- `@nospecialize` - Disable generic specialization for this method
20
21
## Memory Layout and Alignment
22
23
### Alignment Control
24
25
```scala { .api }
26
class align(size: Int, group: String = "") extends scala.annotation.StaticAnnotation
27
```
28
29
**Alignment annotation**:
30
- `@align(size)` - Control memory alignment for fields and structures
31
- `@align(size, group)` - Group-based alignment compatible with JVM `@Contended`
32
33
**Parameters**:
34
- `size: Int` - Alignment size in bytes (must be power of 2)
35
- `group: String` - Optional group name for organizing related fields
36
37
## External Interface Annotations
38
39
### Native Interoperability
40
41
```scala { .api }
42
class extern extends scala.annotation.StaticAnnotation
43
class blocking extends scala.annotation.StaticAnnotation
44
class exported(name: String = "") extends scala.annotation.StaticAnnotation
45
class name(n: String) extends scala.annotation.StaticAnnotation
46
class link(name: String) extends scala.annotation.StaticAnnotation
47
class linkCppRuntime extends scala.annotation.StaticAnnotation
48
class define(name: String, value: String) extends scala.annotation.StaticAnnotation
49
class resolvedAtLinktime extends scala.annotation.StaticAnnotation
50
```
51
52
**External interface annotations**:
53
- `@extern` - Mark objects containing externally-defined members
54
- `@blocking` - Mark methods as potentially blocking (for threading)
55
- `@exported` - Export Scala function to be callable from C
56
- `@name` - Specify external symbol name
57
- `@link` - Link with external library
58
- `@linkCppRuntime` - Link with C++ runtime
59
- `@define` - Set preprocessor define
60
- `@resolvedAtLinktime` - Mark values resolved during linking
61
62
## Memory Model and Threading
63
64
### Memory Consistency
65
66
```scala { .api }
67
class safePublish extends scala.annotation.StaticAnnotation
68
```
69
70
**Memory model annotation**:
71
- `@safePublish` - Follow Java Memory Model for final field initialization and reading
72
- Ensures final fields are safely published across threads
73
- Can be applied to individual fields or entire types
74
75
## Reflection Support
76
77
### Reflective Instantiation
78
79
```scala { .api }
80
class EnableReflectiveInstantiation extends scala.annotation.StaticAnnotation
81
```
82
83
**Reflection annotation**:
84
- `@EnableReflectiveInstantiation` - Enable reflective instantiation for annotated class/trait/object
85
- Allows runtime identification through `scala.scalanative.reflect.Reflect` methods
86
- Applied to types that need runtime reflection capabilities
87
88
## Development Annotations
89
90
### Development Support
91
92
```scala { .api }
93
class stub extends scala.annotation.StaticAnnotation
94
```
95
96
**Development annotation**:
97
- `@stub` - Mark methods as unimplemented stubs
98
99
## Usage Examples
100
101
### Optimization Control
102
103
```scala
104
import scala.scalanative.annotation._
105
106
class MathUtils {
107
// Force inlining for performance-critical methods
108
@alwaysinline
109
def fastSquare(x: Double): Double = x * x
110
111
// Prevent inlining to reduce code size
112
@noinline
113
def largeComplexFunction(): Unit = {
114
// Large method body...
115
}
116
117
// Disable all optimizations for debugging
118
@nooptimize
119
def debugOnlyMethod(): Unit = {
120
// Debug-specific logic
121
}
122
123
// Disable specialization to reduce binary size
124
@nospecialize
125
def genericMethod[T](value: T): T = value
126
}
127
```
128
129
### Memory Alignment
130
131
```scala
132
import scala.scalanative.annotation._
133
import scala.scalanative.unsafe._
134
135
// Align struct fields for performance
136
class AlignedStruct {
137
@align(64) // Cache line alignment
138
var criticalData: Long = 0
139
140
@align(16) // SIMD alignment
141
var vectorData: Ptr[Float] = null
142
143
// Group related fields together (like JVM @Contended)
144
@align(8, "counters")
145
var counter1: Long = 0
146
147
@align(8, "counters")
148
var counter2: Long = 0
149
}
150
151
// Align entire class
152
@align(32)
153
class CacheAlignedClass {
154
var data: Int = 0
155
}
156
```
157
158
### External C Interface
159
160
```scala
161
import scala.scalanative.annotation._
162
import scala.scalanative.unsafe._
163
164
// External C library declarations
165
@extern
166
@link("m") // Link with math library (-lm)
167
object LibMath {
168
// C function: double sin(double x)
169
def sin(x: CDouble): CDouble = extern
170
171
// C function: double cos(double x)
172
def cos(x: CDouble): CDouble = extern
173
174
// Blocking I/O function
175
@blocking
176
def sleep(seconds: CUnsignedInt): CUnsignedInt = extern
177
}
178
179
// External C library with custom names
180
@extern
181
@link("custom")
182
object CustomLib {
183
// Map Scala name to C symbol name
184
@name("c_process_data")
185
def processData(data: Ptr[Byte], size: CSize): CInt = extern
186
187
// Define preprocessor macro
188
@define("BUFFER_SIZE", "1024")
189
def getBufferSize(): CSize = extern
190
}
191
```
192
193
### Exported Functions
194
195
```scala
196
import scala.scalanative.annotation._
197
import scala.scalanative.unsafe._
198
199
// Export Scala functions to be callable from C
200
object ScalaCallbacks {
201
// Export with default name (scalanative_callback)
202
@exported
203
def callback(value: CInt): CInt = {
204
value * 2
205
}
206
207
// Export with custom C symbol name
208
@exported("my_custom_callback")
209
def customCallback(data: Ptr[Byte], size: CSize): Unit = {
210
// Process data...
211
}
212
213
// Export function pointer type
214
@exported("error_handler")
215
def errorHandler(code: CInt, message: CString): Unit = {
216
val msg = fromCString(message)
217
println(s"Error $code: $msg")
218
}
219
}
220
```
221
222
### Link-time Resolution
223
224
```scala
225
import scala.scalanative.annotation._
226
import scala.scalanative.unsafe._
227
228
object LinkTimeConfig {
229
// Values determined at link time
230
@resolvedAtLinktime
231
def isDebugBuild(): Boolean = resolved
232
233
@resolvedAtLinktime
234
def getTargetPlatform(): CString = resolved
235
236
@resolvedAtLinktime
237
def getBuildTimestamp(): CLong = resolved
238
239
// Use in conditional compilation
240
def logDebug(message: String): Unit = {
241
if (isDebugBuild()) {
242
println(s"DEBUG: $message")
243
}
244
}
245
}
246
```
247
248
### Development Stubs
249
250
```scala
251
import scala.scalanative.annotation._
252
253
trait NetworkInterface {
254
def connect(host: String, port: Int): Boolean
255
def sendData(data: Array[Byte]): Int
256
def disconnect(): Unit
257
}
258
259
class NetworkImplementation extends NetworkInterface {
260
def connect(host: String, port: Int): Boolean = {
261
// Full implementation
262
true
263
}
264
265
@stub
266
def sendData(data: Array[Byte]): Int = {
267
// TODO: Implement data sending
268
throw new UnsupportedOperationException("sendData not implemented yet")
269
}
270
271
@stub
272
def disconnect(): Unit = {
273
// TODO: Implement disconnection
274
throw new UnsupportedOperationException("disconnect not implemented yet")
275
}
276
}
277
```
278
279
### Complex External Library Integration
280
281
```scala
282
import scala.scalanative.annotation._
283
import scala.scalanative.unsafe._
284
285
// Complex C++ library integration
286
@extern
287
@linkCppRuntime
288
@link("mylib")
289
@define("MYLIB_VERSION", "2")
290
object MyLibrary {
291
// C++ function with name mangling
292
@name("_Z10processFooPN6MyLib4DataE")
293
def processFoo(data: Ptr[Byte]): CInt = extern
294
295
// Initialize library (must be called first)
296
@name("MyLib_Initialize")
297
def initialize(): CBool = extern
298
299
// Cleanup (should be called on exit)
300
@name("MyLib_Shutdown")
301
def shutdown(): Unit = extern
302
303
// Async function that may block
304
@blocking
305
@name("MyLib_AsyncProcess")
306
def asyncProcess(data: Ptr[Byte], callback: CFuncPtr1[CInt, Unit]): Unit = extern
307
}
308
309
// Usage with proper initialization
310
object MyApp {
311
def main(args: Array[String]): Unit = {
312
if (MyLibrary.initialize()) {
313
try {
314
// Use library functions...
315
Zone.acquire { implicit z =>
316
val data = alloc[Byte](1024)
317
val result = MyLibrary.processFoo(data)
318
println(s"Processing result: $result")
319
}
320
} finally {
321
MyLibrary.shutdown()
322
}
323
} else {
324
println("Failed to initialize library")
325
}
326
}
327
}
328
```
329
330
### Performance-Critical Code
331
332
```scala
333
import scala.scalanative.annotation._
334
import scala.scalanative.unsafe._
335
336
class HighPerformanceMatrix {
337
@align(64) // Cache line aligned
338
private var data: Ptr[Double] = _
339
340
private var rows: Int = _
341
private var cols: Int = _
342
343
def initialize(r: Int, c: Int): Unit = {
344
Zone.acquire { implicit z =>
345
rows = r
346
cols = c
347
data = alloc[Double](rows * cols)
348
}
349
}
350
351
// Critical path - always inline
352
@alwaysinline
353
def get(row: Int, col: Int): Double = {
354
data(row * cols + col)
355
}
356
357
// Critical path - always inline
358
@alwaysinline
359
def set(row: Int, col: Int, value: Double): Unit = {
360
data(row * cols + col) = value
361
}
362
363
// Large method - don't inline to save code space
364
@noinline
365
def multiply(other: HighPerformanceMatrix): HighPerformanceMatrix = {
366
val result = new HighPerformanceMatrix
367
result.initialize(rows, other.cols)
368
369
// Matrix multiplication implementation...
370
for (i <- 0 until rows) {
371
for (j <- 0 until other.cols) {
372
var sum = 0.0
373
for (k <- 0 until cols) {
374
sum += get(i, k) * other.get(k, j)
375
}
376
result.set(i, j, sum)
377
}
378
}
379
380
result
381
}
382
}
383
```
384
385
## Best Practices
386
387
1. **Use @alwaysinline sparingly** - only for small, performance-critical methods
388
2. **Apply @align strategically** - consider cache lines (64 bytes) and SIMD requirements (16 bytes)
389
3. **Mark blocking operations** - essential for proper threading behavior
390
4. **Use @extern consistently** - group related external functions in objects
391
5. **Export functions carefully** - ensure proper memory management across boundaries
392
6. **Link libraries explicitly** - specify all required libraries with @link
393
7. **Stub incomplete implementations** - use @stub during development for clarity
394
8. **Test with different optimization levels** - ensure annotations work as expected