0
# JNA Pointer References (ptr Package)
1
2
This document covers JNA's ptr package, which provides by-reference parameter passing functionality essential for interacting with native functions that modify parameters.
3
4
## Core Imports
5
6
```java { .api }
7
import com.sun.jna.ptr.*;
8
9
// Specific reference types
10
import com.sun.jna.ptr.IntByReference;
11
import com.sun.jna.ptr.LongByReference;
12
import com.sun.jna.ptr.ByteByReference;
13
import com.sun.jna.ptr.ShortByReference;
14
import com.sun.jna.ptr.FloatByReference;
15
import com.sun.jna.ptr.DoubleByReference;
16
import com.sun.jna.ptr.PointerByReference;
17
import com.sun.jna.ptr.NativeLongByReference;
18
```
19
20
## ByReference Abstract Class - Base for Reference Types
21
22
The `ByReference` abstract class provides the foundation for pass-by-reference parameter types:
23
24
```java { .api }
25
/**
26
* Base class for pointer-to-type functionality used in C code
27
* to return values to the caller in addition to function results
28
*/
29
public abstract class ByReference extends PointerType {
30
/**
31
* Constructor allocating memory for the data type
32
* @param dataSize Size in bytes of the data type
33
*/
34
protected ByReference(int dataSize);
35
}
36
```
37
38
## Primitive ByReference Classes
39
40
### IntByReference - Integer Pass-by-Reference
41
42
```java { .api }
43
/**
44
* Provides pass-by-reference for int values
45
*/
46
public class IntByReference extends ByReference {
47
/**
48
* Create with zero value
49
*/
50
public IntByReference();
51
52
/**
53
* Create with specific value
54
* @param value Initial int value
55
*/
56
public IntByReference(int value);
57
58
/**
59
* Set the int value
60
* @param value New int value
61
*/
62
public void setValue(int value);
63
64
/**
65
* Get the int value
66
* @return Current int value
67
*/
68
public int getValue();
69
}
70
```
71
72
### LongByReference - Long Pass-by-Reference
73
74
```java { .api }
75
/**
76
* Provides pass-by-reference for long values
77
*/
78
public class LongByReference extends ByReference {
79
/**
80
* Create with zero value
81
*/
82
public LongByReference();
83
84
/**
85
* Create with specific value
86
* @param value Initial long value
87
*/
88
public LongByReference(long value);
89
90
/**
91
* Set the long value
92
* @param value New long value
93
*/
94
public void setValue(long value);
95
96
/**
97
* Get the long value
98
* @return Current long value
99
*/
100
public long getValue();
101
}
102
```
103
104
### ByteByReference - Byte Pass-by-Reference
105
106
```java { .api }
107
/**
108
* Provides pass-by-reference for byte values
109
*/
110
public class ByteByReference extends ByReference {
111
/**
112
* Create with zero value
113
*/
114
public ByteByReference();
115
116
/**
117
* Create with specific value
118
* @param value Initial byte value
119
*/
120
public ByteByReference(byte value);
121
122
/**
123
* Set the byte value
124
* @param value New byte value
125
*/
126
public void setValue(byte value);
127
128
/**
129
* Get the byte value
130
* @return Current byte value
131
*/
132
public byte getValue();
133
}
134
```
135
136
### ShortByReference - Short Pass-by-Reference
137
138
```java { .api }
139
/**
140
* Provides pass-by-reference for short values
141
*/
142
public class ShortByReference extends ByReference {
143
/**
144
* Create with zero value
145
*/
146
public ShortByReference();
147
148
/**
149
* Create with specific value
150
* @param value Initial short value
151
*/
152
public ShortByReference(short value);
153
154
/**
155
* Set the short value
156
* @param value New short value
157
*/
158
public void setValue(short value);
159
160
/**
161
* Get the short value
162
* @return Current short value
163
*/
164
public short getValue();
165
}
166
```
167
168
### FloatByReference - Float Pass-by-Reference
169
170
```java { .api }
171
/**
172
* Provides pass-by-reference for float values
173
*/
174
public class FloatByReference extends ByReference {
175
/**
176
* Create with zero value
177
*/
178
public FloatByReference();
179
180
/**
181
* Create with specific value
182
* @param value Initial float value
183
*/
184
public FloatByReference(float value);
185
186
/**
187
* Set the float value
188
* @param value New float value
189
*/
190
public void setValue(float value);
191
192
/**
193
* Get the float value
194
* @return Current float value
195
*/
196
public float getValue();
197
}
198
```
199
200
### DoubleByReference - Double Pass-by-Reference
201
202
```java { .api }
203
/**
204
* Provides pass-by-reference for double values
205
*/
206
public class DoubleByReference extends ByReference {
207
/**
208
* Create with zero value
209
*/
210
public DoubleByReference();
211
212
/**
213
* Create with specific value
214
* @param value Initial double value
215
*/
216
public DoubleByReference(double value);
217
218
/**
219
* Set the double value
220
* @param value New double value
221
*/
222
public void setValue(double value);
223
224
/**
225
* Get the double value
226
* @return Current double value
227
*/
228
public double getValue();
229
}
230
```
231
232
## Pointer and Platform-Specific References
233
234
### PointerByReference - Pointer Pass-by-Reference
235
236
```java { .api }
237
/**
238
* Provides pass-by-reference for Pointer values (void** in C)
239
*/
240
public class PointerByReference extends ByReference {
241
/**
242
* Create with null pointer
243
*/
244
public PointerByReference();
245
246
/**
247
* Create with specific pointer
248
* @param value Initial pointer value
249
*/
250
public PointerByReference(Pointer value);
251
252
/**
253
* Set the pointer value
254
* @param value New pointer value
255
*/
256
public void setValue(Pointer value);
257
258
/**
259
* Get the pointer value
260
* @return Current pointer value
261
*/
262
public Pointer getValue();
263
}
264
```
265
266
### NativeLongByReference - Platform-Specific Long Reference
267
268
```java { .api }
269
/**
270
* Provides pass-by-reference for NativeLong values
271
* (platform-specific long type)
272
*/
273
public class NativeLongByReference extends ByReference {
274
/**
275
* Create with zero value
276
*/
277
public NativeLongByReference();
278
279
/**
280
* Create with specific value
281
* @param value Initial NativeLong value
282
*/
283
public NativeLongByReference(NativeLong value);
284
285
/**
286
* Set the NativeLong value
287
* @param value New NativeLong value
288
*/
289
public void setValue(NativeLong value);
290
291
/**
292
* Get the NativeLong value
293
* @return Current NativeLong value
294
*/
295
public NativeLong getValue();
296
}
297
```
298
299
## Usage Examples
300
301
### Basic Pass-by-Reference Pattern
302
303
```java
304
// Native function that modifies parameters:
305
// int divide(int dividend, int divisor, int* quotient, int* remainder)
306
public interface MathLibrary extends Library {
307
MathLibrary INSTANCE = Native.loadLibrary("mathlib", MathLibrary.class);
308
309
/**
310
* Divide two numbers, returning quotient and remainder by reference
311
* @param dividend Number to divide
312
* @param divisor Number to divide by
313
* @param quotient Output parameter for quotient
314
* @param remainder Output parameter for remainder
315
* @return 0 on success, error code on failure
316
*/
317
int divide(int dividend, int divisor,
318
IntByReference quotient, IntByReference remainder);
319
}
320
321
// Usage
322
IntByReference quotient = new IntByReference();
323
IntByReference remainder = new IntByReference();
324
325
int result = MathLibrary.INSTANCE.divide(17, 5, quotient, remainder);
326
if (result == 0) {
327
System.out.println("Quotient: " + quotient.getValue()); // 3
328
System.out.println("Remainder: " + remainder.getValue()); // 2
329
}
330
```
331
332
### Memory Allocation Pattern
333
334
```java
335
// Native function: void* malloc(size_t size)
336
// Native function: void free(void* ptr)
337
public interface CLibrary extends Library {
338
CLibrary INSTANCE = Native.loadLibrary("c", CLibrary.class);
339
340
Pointer malloc(long size);
341
void free(Pointer ptr);
342
343
// Function that allocates memory and returns pointer via parameter
344
int allocateBuffer(long size, PointerByReference buffer);
345
}
346
347
// Usage
348
PointerByReference bufferRef = new PointerByReference();
349
int result = CLibrary.INSTANCE.allocateBuffer(1024, bufferRef);
350
351
if (result == 0) {
352
Pointer buffer = bufferRef.getValue();
353
// Use the allocated buffer
354
buffer.setInt(0, 42);
355
356
// Clean up
357
CLibrary.INSTANCE.free(buffer);
358
}
359
```
360
361
### Windows API Examples
362
363
```java
364
// Windows API functions using by-reference parameters
365
public interface Kernel32 extends StdCallLibrary {
366
Kernel32 INSTANCE = Native.loadLibrary("kernel32", Kernel32.class);
367
368
/**
369
* Get system time
370
* @param systemTime Structure to receive time
371
*/
372
void GetSystemTime(SystemTimeStructure systemTime);
373
374
/**
375
* Get module handle by name
376
* @param moduleName Name of module (null for current process)
377
* @param moduleHandle Output parameter for module handle
378
* @return true on success
379
*/
380
boolean GetModuleHandleEx(int flags, String moduleName,
381
PointerByReference moduleHandle);
382
}
383
384
// Usage
385
PointerByReference moduleHandle = new PointerByReference();
386
boolean success = Kernel32.INSTANCE.GetModuleHandleEx(0, null, moduleHandle);
387
388
if (success) {
389
Pointer handle = moduleHandle.getValue();
390
System.out.println("Module handle: " + handle);
391
}
392
```
393
394
### Multiple Output Parameters
395
396
```java
397
// Function with multiple output parameters
398
public interface GeometryLibrary extends Library {
399
GeometryLibrary INSTANCE = Native.loadLibrary("geometry", GeometryLibrary.class);
400
401
/**
402
* Calculate circle properties
403
* @param radius Input radius
404
* @param area Output parameter for area
405
* @param circumference Output parameter for circumference
406
* @param diameter Output parameter for diameter
407
*/
408
void calculateCircle(double radius,
409
DoubleByReference area,
410
DoubleByReference circumference,
411
DoubleByReference diameter);
412
}
413
414
// Usage
415
DoubleByReference area = new DoubleByReference();
416
DoubleByReference circumference = new DoubleByReference();
417
DoubleByReference diameter = new DoubleByReference();
418
419
GeometryLibrary.INSTANCE.calculateCircle(5.0, area, circumference, diameter);
420
421
System.out.println("Area: " + area.getValue());
422
System.out.println("Circumference: " + circumference.getValue());
423
System.out.println("Diameter: " + diameter.getValue());
424
```
425
426
## Best Practices
427
428
### Initialization and Cleanup
429
430
```java
431
// Always initialize reference values when needed
432
IntByReference counter = new IntByReference(0); // Start with known value
433
434
// Check return values when functions can fail
435
PointerByReference ptr = new PointerByReference();
436
int result = someFunction(ptr);
437
if (result != 0) {
438
// Handle error - ptr.getValue() may be invalid
439
return;
440
}
441
442
// Use the returned pointer
443
Pointer validPtr = ptr.getValue();
444
```
445
446
### Thread Safety
447
448
```java
449
// ByReference objects are not thread-safe
450
// Create separate instances for concurrent access
451
public class ThreadSafeCounter {
452
public int increment(int value) {
453
IntByReference ref = new IntByReference(value);
454
nativeIncrementFunction(ref);
455
return ref.getValue();
456
}
457
}
458
```
459
460
The ptr package is essential for interacting with native functions that modify parameters or return multiple values, providing type-safe pass-by-reference semantics that match C/C++ pointer parameters.