CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-net-java-dev-jna--jna

Java Native Access (JNA) provides Java programs easy access to native shared libraries without writing anything but Java code - no JNI or native code is required.

Pending
Overview
Eval results
Files

ptr-package.mddocs/

JNA Pointer References (ptr Package)

This document covers JNA's ptr package, which provides by-reference parameter passing functionality essential for interacting with native functions that modify parameters.

Core Imports

import com.sun.jna.ptr.*;

// Specific reference types
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.LongByReference;
import com.sun.jna.ptr.ByteByReference;
import com.sun.jna.ptr.ShortByReference;
import com.sun.jna.ptr.FloatByReference;
import com.sun.jna.ptr.DoubleByReference;
import com.sun.jna.ptr.PointerByReference;
import com.sun.jna.ptr.NativeLongByReference;

ByReference Abstract Class - Base for Reference Types

The ByReference abstract class provides the foundation for pass-by-reference parameter types:

/**
 * Base class for pointer-to-type functionality used in C code
 * to return values to the caller in addition to function results
 */
public abstract class ByReference extends PointerType {
    /**
     * Constructor allocating memory for the data type
     * @param dataSize Size in bytes of the data type
     */
    protected ByReference(int dataSize);
}

Primitive ByReference Classes

IntByReference - Integer Pass-by-Reference

/**
 * Provides pass-by-reference for int values
 */
public class IntByReference extends ByReference {
    /**
     * Create with zero value
     */
    public IntByReference();
    
    /**
     * Create with specific value
     * @param value Initial int value
     */
    public IntByReference(int value);
    
    /**
     * Set the int value
     * @param value New int value
     */
    public void setValue(int value);
    
    /**
     * Get the int value
     * @return Current int value
     */
    public int getValue();
}

LongByReference - Long Pass-by-Reference

/**
 * Provides pass-by-reference for long values
 */
public class LongByReference extends ByReference {
    /**
     * Create with zero value
     */
    public LongByReference();
    
    /**
     * Create with specific value
     * @param value Initial long value
     */
    public LongByReference(long value);
    
    /**
     * Set the long value
     * @param value New long value
     */
    public void setValue(long value);
    
    /**
     * Get the long value
     * @return Current long value
     */
    public long getValue();
}

ByteByReference - Byte Pass-by-Reference

/**
 * Provides pass-by-reference for byte values
 */
public class ByteByReference extends ByReference {
    /**
     * Create with zero value
     */
    public ByteByReference();
    
    /**
     * Create with specific value
     * @param value Initial byte value
     */
    public ByteByReference(byte value);
    
    /**
     * Set the byte value
     * @param value New byte value
     */
    public void setValue(byte value);
    
    /**
     * Get the byte value
     * @return Current byte value
     */
    public byte getValue();
}

ShortByReference - Short Pass-by-Reference

/**
 * Provides pass-by-reference for short values
 */
public class ShortByReference extends ByReference {
    /**
     * Create with zero value
     */
    public ShortByReference();
    
    /**
     * Create with specific value
     * @param value Initial short value
     */
    public ShortByReference(short value);
    
    /**
     * Set the short value
     * @param value New short value
     */
    public void setValue(short value);
    
    /**
     * Get the short value
     * @return Current short value
     */
    public short getValue();
}

FloatByReference - Float Pass-by-Reference

/**
 * Provides pass-by-reference for float values
 */
public class FloatByReference extends ByReference {
    /**
     * Create with zero value
     */
    public FloatByReference();
    
    /**
     * Create with specific value
     * @param value Initial float value
     */
    public FloatByReference(float value);
    
    /**
     * Set the float value
     * @param value New float value
     */
    public void setValue(float value);
    
    /**
     * Get the float value
     * @return Current float value
     */
    public float getValue();
}

DoubleByReference - Double Pass-by-Reference

/**
 * Provides pass-by-reference for double values
 */
public class DoubleByReference extends ByReference {
    /**
     * Create with zero value
     */
    public DoubleByReference();
    
    /**
     * Create with specific value
     * @param value Initial double value
     */
    public DoubleByReference(double value);
    
    /**
     * Set the double value
     * @param value New double value
     */
    public void setValue(double value);
    
    /**
     * Get the double value
     * @return Current double value
     */
    public double getValue();
}

Pointer and Platform-Specific References

PointerByReference - Pointer Pass-by-Reference

/**
 * Provides pass-by-reference for Pointer values (void** in C)
 */
public class PointerByReference extends ByReference {
    /**
     * Create with null pointer
     */
    public PointerByReference();
    
    /**
     * Create with specific pointer
     * @param value Initial pointer value
     */
    public PointerByReference(Pointer value);
    
    /**
     * Set the pointer value
     * @param value New pointer value
     */
    public void setValue(Pointer value);
    
    /**
     * Get the pointer value
     * @return Current pointer value
     */
    public Pointer getValue();
}

NativeLongByReference - Platform-Specific Long Reference

/**
 * Provides pass-by-reference for NativeLong values
 * (platform-specific long type)
 */
public class NativeLongByReference extends ByReference {
    /**
     * Create with zero value
     */
    public NativeLongByReference();
    
    /**
     * Create with specific value
     * @param value Initial NativeLong value
     */
    public NativeLongByReference(NativeLong value);
    
    /**
     * Set the NativeLong value
     * @param value New NativeLong value
     */
    public void setValue(NativeLong value);
    
    /**
     * Get the NativeLong value
     * @return Current NativeLong value
     */
    public NativeLong getValue();
}

Usage Examples

Basic Pass-by-Reference Pattern

// Native function that modifies parameters:
// int divide(int dividend, int divisor, int* quotient, int* remainder)
public interface MathLibrary extends Library {
    MathLibrary INSTANCE = Native.loadLibrary("mathlib", MathLibrary.class);
    
    /**
     * Divide two numbers, returning quotient and remainder by reference
     * @param dividend Number to divide
     * @param divisor Number to divide by
     * @param quotient Output parameter for quotient
     * @param remainder Output parameter for remainder
     * @return 0 on success, error code on failure
     */
    int divide(int dividend, int divisor, 
               IntByReference quotient, IntByReference remainder);
}

// Usage
IntByReference quotient = new IntByReference();
IntByReference remainder = new IntByReference();

int result = MathLibrary.INSTANCE.divide(17, 5, quotient, remainder);
if (result == 0) {
    System.out.println("Quotient: " + quotient.getValue());   // 3
    System.out.println("Remainder: " + remainder.getValue()); // 2
}

Memory Allocation Pattern

// Native function: void* malloc(size_t size)
// Native function: void free(void* ptr)
public interface CLibrary extends Library {
    CLibrary INSTANCE = Native.loadLibrary("c", CLibrary.class);
    
    Pointer malloc(long size);
    void free(Pointer ptr);
    
    // Function that allocates memory and returns pointer via parameter
    int allocateBuffer(long size, PointerByReference buffer);
}

// Usage
PointerByReference bufferRef = new PointerByReference();
int result = CLibrary.INSTANCE.allocateBuffer(1024, bufferRef);

if (result == 0) {
    Pointer buffer = bufferRef.getValue();
    // Use the allocated buffer
    buffer.setInt(0, 42);
    
    // Clean up
    CLibrary.INSTANCE.free(buffer);
}

Windows API Examples

// Windows API functions using by-reference parameters
public interface Kernel32 extends StdCallLibrary {
    Kernel32 INSTANCE = Native.loadLibrary("kernel32", Kernel32.class);
    
    /**
     * Get system time
     * @param systemTime Structure to receive time
     */
    void GetSystemTime(SystemTimeStructure systemTime);
    
    /**
     * Get module handle by name
     * @param moduleName Name of module (null for current process)
     * @param moduleHandle Output parameter for module handle
     * @return true on success
     */
    boolean GetModuleHandleEx(int flags, String moduleName, 
                             PointerByReference moduleHandle);
}

// Usage
PointerByReference moduleHandle = new PointerByReference();
boolean success = Kernel32.INSTANCE.GetModuleHandleEx(0, null, moduleHandle);

if (success) {
    Pointer handle = moduleHandle.getValue();
    System.out.println("Module handle: " + handle);
}

Multiple Output Parameters

// Function with multiple output parameters
public interface GeometryLibrary extends Library {
    GeometryLibrary INSTANCE = Native.loadLibrary("geometry", GeometryLibrary.class);
    
    /**
     * Calculate circle properties
     * @param radius Input radius
     * @param area Output parameter for area
     * @param circumference Output parameter for circumference
     * @param diameter Output parameter for diameter
     */
    void calculateCircle(double radius,
                        DoubleByReference area,
                        DoubleByReference circumference, 
                        DoubleByReference diameter);
}

// Usage
DoubleByReference area = new DoubleByReference();
DoubleByReference circumference = new DoubleByReference();
DoubleByReference diameter = new DoubleByReference();

GeometryLibrary.INSTANCE.calculateCircle(5.0, area, circumference, diameter);

System.out.println("Area: " + area.getValue());
System.out.println("Circumference: " + circumference.getValue()); 
System.out.println("Diameter: " + diameter.getValue());

Best Practices

Initialization and Cleanup

// Always initialize reference values when needed
IntByReference counter = new IntByReference(0);  // Start with known value

// Check return values when functions can fail
PointerByReference ptr = new PointerByReference();
int result = someFunction(ptr);
if (result != 0) {
    // Handle error - ptr.getValue() may be invalid
    return;
}

// Use the returned pointer
Pointer validPtr = ptr.getValue();

Thread Safety

// ByReference objects are not thread-safe
// Create separate instances for concurrent access
public class ThreadSafeCounter {
    public int increment(int value) {
        IntByReference ref = new IntByReference(value);
        nativeIncrementFunction(ref);
        return ref.getValue();
    }
}

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.

Install with Tessl CLI

npx tessl i tessl/maven-net-java-dev-jna--jna

docs

index.md

memory-management.md

ptr-package.md

structures-types.md

windows.md

tile.json