or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdmemory-management.mdptr-package.mdstructures-types.mdwindows.md

structures-types.mddocs/

0

# JNA Structures & Type Mapping

1

2

This document covers JNA's structure mapping system, unions, custom type conversion, and callback functionality for seamless Java-to-native type interoperability.

3

4

## Core Imports

5

6

```java { .api }

7

import com.sun.jna.Structure;

8

import com.sun.jna.Union;

9

import com.sun.jna.IntegerType;

10

import com.sun.jna.NativeLong;

11

import com.sun.jna.NativeMapped;

12

import com.sun.jna.TypeMapper;

13

import com.sun.jna.Callback;

14

```

15

16

## Structure Class - Java to C Struct Mapping

17

18

The `Structure` class provides automatic mapping between Java classes and C structures:

19

20

```java { .api }

21

/**

22

* Base class for mapping Java objects to native structures

23

*/

24

public abstract class Structure {

25

/**

26

* Default constructor - allocates new native memory

27

*/

28

public Structure();

29

30

/**

31

* Constructor using existing memory

32

* @param p Pointer to existing structure memory

33

*/

34

public Structure(Pointer p);

35

36

/**

37

* Read structure fields from native memory

38

*/

39

public void read();

40

41

/**

42

* Write structure fields to native memory

43

*/

44

public void write();

45

46

/**

47

* Get size of structure in bytes

48

* @return Structure size including padding

49

*/

50

public int size();

51

52

/**

53

* Get pointer to structure memory

54

* @return Pointer to native structure

55

*/

56

public Pointer getPointer();

57

58

/**

59

* Read specific field from native memory

60

* @param fieldName Name of field to read

61

*/

62

public void readField(String fieldName);

63

64

/**

65

* Write specific field to native memory

66

* @param fieldName Name of field to write

67

*/

68

public void writeField(String fieldName);

69

70

/**

71

* Enable automatic read after native calls

72

* @param auto true to enable auto-read

73

*/

74

public void setAutoRead(boolean auto);

75

76

/**

77

* Enable automatic write before native calls

78

* @param auto true to enable auto-write

79

*/

80

public void setAutoWrite(boolean auto);

81

82

/**

83

* Get field order for structure layout

84

* Must be implemented by subclasses

85

* @return List of field names in memory order

86

*/

87

protected abstract List<String> getFieldOrder();

88

89

// Static utility methods

90

91

/**

92

* Create new structure instance

93

* @param type Structure class

94

* @return New instance of structure

95

*/

96

public static Structure newInstance(Class<?> type);

97

98

/**

99

* Create structure instance at pointer

100

* @param type Structure class

101

* @param p Pointer to existing memory

102

* @return Structure instance using existing memory

103

*/

104

public static Structure newInstance(Class<?> type, Pointer p);

105

106

/**

107

* Auto-read array of structures

108

* @param structures Array of structures to read

109

*/

110

public static void autoRead(Structure[] structures);

111

112

/**

113

* Auto-write array of structures

114

* @param structures Array of structures to write

115

*/

116

public static void autoWrite(Structure[] structures);

117

118

// Inner marker interfaces for parameter passing

119

120

/**

121

* Marker interface for pass-by-value structures

122

*/

123

public interface ByValue { }

124

125

/**

126

* Marker interface for pass-by-reference structures

127

*/

128

public interface ByReference { }

129

}

130

```

131

132

## Basic Structure Definition

133

134

```java { .api }

135

// Simple C structure mapping

136

public static class Point extends Structure {

137

public int x;

138

public int y;

139

140

public Point() {

141

super();

142

}

143

144

public Point(int x, int y) {

145

this.x = x;

146

this.y = y;

147

write(); // Write fields to native memory

148

}

149

150

public Point(Pointer p) {

151

super(p);

152

read(); // Read from existing memory

153

}

154

155

@Override

156

protected List<String> getFieldOrder() {

157

return Arrays.asList("x", "y");

158

}

159

160

@Override

161

public String toString() {

162

return String.format("Point{x=%d, y=%d}", x, y);

163

}

164

}

165

166

// Usage

167

Point p1 = new Point(10, 20); // Create and initialize

168

Point p2 = new Point(); // Create uninitialized

169

p2.x = 30; p2.y = 40; p2.write(); // Set fields and write

170

```

171

172

## Advanced Structure Features

173

174

```java { .api }

175

// Structure with various field types

176

public static class ComplexStruct extends Structure {

177

public byte byteField;

178

public short shortField;

179

public int intField;

180

public long longField;

181

public float floatField;

182

public double doubleField;

183

public Pointer ptrField;

184

public String stringField; // Converted to/from native string

185

186

// Array fields

187

public int[] intArray = new int[10];

188

public byte[] bytes = new byte[256];

189

190

// Nested structure

191

public Point location = new Point();

192

193

@Override

194

protected List<String> getFieldOrder() {

195

return Arrays.asList(

196

"byteField", "shortField", "intField", "longField",

197

"floatField", "doubleField", "ptrField", "stringField",

198

"intArray", "bytes", "location"

199

);

200

}

201

}

202

203

// Structure with custom field handling

204

public static class CustomStruct extends Structure {

205

public int flags;

206

public String name;

207

208

@Override

209

protected List<String> getFieldOrder() {

210

return Arrays.asList("flags", "name");

211

}

212

213

@Override

214

public void read() {

215

super.read();

216

// Custom post-read processing

217

if (name != null) {

218

name = name.trim();

219

}

220

}

221

222

@Override

223

public void write() {

224

// Custom pre-write processing

225

if (name != null && name.length() > 255) {

226

name = name.substring(0, 255);

227

}

228

super.write();

229

}

230

}

231

```

232

233

## Pass By Value vs By Reference

234

235

```java { .api }

236

// Pass by value - structure copied to native stack

237

public static class PointByValue extends Structure implements Structure.ByValue {

238

public int x, y;

239

240

@Override

241

protected List<String> getFieldOrder() {

242

return Arrays.asList("x", "y");

243

}

244

}

245

246

// Pass by reference - pointer to structure passed

247

public static class PointByReference extends Structure implements Structure.ByReference {

248

public int x, y;

249

250

@Override

251

protected List<String> getFieldOrder() {

252

return Arrays.asList("x", "y");

253

}

254

}

255

256

// Native function declarations

257

public interface Graphics extends Library {

258

/**

259

* Function expecting structure by value

260

* void drawPoint(Point point);

261

*/

262

void drawPoint(PointByValue point);

263

264

/**

265

* Function expecting structure by reference

266

* void updatePoint(Point* point);

267

*/

268

void updatePoint(PointByReference point);

269

}

270

271

// Usage

272

PointByValue p1 = new PointByValue();

273

p1.x = 10; p1.y = 20;

274

Graphics.INSTANCE.drawPoint(p1); // Structure copied

275

276

PointByReference p2 = new PointByReference();

277

p2.x = 30; p2.y = 40; p2.write();

278

Graphics.INSTANCE.updatePoint(p2); // Pointer passed

279

p2.read(); // Read any changes made by native function

280

```

281

282

## Union Class - Shared Memory Fields

283

284

```java { .api }

285

/**

286

* Represents a native union where all fields share memory

287

*/

288

public abstract class Union extends Structure {

289

/**

290

* Set active field type by class

291

* @param type Class of field to make active

292

*/

293

public void setType(Class<?> type);

294

295

/**

296

* Set active field type by field name

297

* @param fieldName Name of field to make active

298

*/

299

public void setType(String fieldName);

300

301

/**

302

* Read value as specific type

303

* @param type Type to read value as

304

* @return Value cast to specified type

305

*/

306

public Object getTypedValue(Class<?> type);

307

308

/**

309

* Set value and active type

310

* @param object Value to set (determines active type)

311

*/

312

public void setTypedValue(Object object);

313

}

314

315

// Union example

316

public static class IntOrFloat extends Union {

317

public int intValue;

318

public float floatValue;

319

320

@Override

321

protected List<String> getFieldOrder() {

322

return Arrays.asList("intValue", "floatValue");

323

}

324

}

325

326

// Usage

327

IntOrFloat u = new IntOrFloat();

328

u.setType("intValue"); // Set active type

329

u.intValue = 42; // Set int value

330

u.write(); // Write to memory

331

332

u.setType("floatValue"); // Change active type

333

u.read(); // Read as float

334

float f = u.floatValue; // Same memory, different interpretation

335

336

// Typed access

337

u.setTypedValue(3.14f); // Sets floatValue and active type

338

Object value = u.getTypedValue(Float.class); // Gets as float

339

```

340

341

## PointerType Class - Type-Safe Native Pointers

342

343

The `PointerType` abstract class provides a foundation for creating type-safe native pointer wrappers:

344

345

```java { .api }

346

/**

347

* Base class for creating type-safe native pointer types

348

*/

349

public abstract class PointerType implements NativeMapped {

350

/**

351

* Default constructor wraps a NULL pointer

352

*/

353

protected PointerType();

354

355

/**

356

* Constructor using existing pointer

357

* @param p Pointer to wrap

358

*/

359

protected PointerType(Pointer p);

360

361

/**

362

* Get the associated native pointer

363

* @return Native pointer representation

364

*/

365

public Pointer getPointer();

366

367

/**

368

* Set the associated native pointer

369

* @param p Pointer to set

370

*/

371

public void setPointer(Pointer p);

372

373

// NativeMapped implementation

374

public Class<?> nativeType();

375

public Object toNative();

376

public Object fromNative(Object nativeValue, FromNativeContext context);

377

378

// Object methods

379

public int hashCode();

380

public boolean equals(Object o);

381

public String toString();

382

}

383

```

384

385

### PointerType Usage Examples

386

387

```java

388

// Create custom pointer type for handles

389

public class WindowHandle extends PointerType {

390

public WindowHandle() { super(); }

391

public WindowHandle(Pointer p) { super(p); }

392

}

393

394

// Use in native library interface

395

public interface WindowsAPI extends Library {

396

WindowHandle CreateWindow(String className, String windowName, int style,

397

int x, int y, int width, int height,

398

WindowHandle parent, Pointer menu,

399

Pointer instance, Pointer param);

400

boolean DestroyWindow(WindowHandle window);

401

boolean ShowWindow(WindowHandle window, int cmdShow);

402

}

403

404

// Usage

405

WindowsAPI api = Native.loadLibrary("user32", WindowsAPI.class);

406

WindowHandle window = api.CreateWindow("STATIC", "Test", 0,

407

100, 100, 300, 200,

408

null, null, null, null);

409

api.ShowWindow(window, 1);

410

```

411

412

## Integer Types - Platform-Specific Sizes

413

414

```java { .api }

415

/**

416

* Base class for platform-specific integer types

417

*/

418

public abstract class IntegerType extends Number implements NativeMapped {

419

/**

420

* Create signed zero-valued integer

421

* @param size Size in bytes (1, 2, 4, or 8)

422

*/

423

public IntegerType(int size);

424

425

/**

426

* Create optionally unsigned integer

427

* @param size Size in bytes

428

* @param unsigned true for unsigned type

429

*/

430

public IntegerType(int size, boolean unsigned);

431

432

/**

433

* Create with specific value

434

* @param size Size in bytes

435

* @param value Initial value

436

* @param unsigned true for unsigned type

437

*/

438

public IntegerType(int size, long value, boolean unsigned);

439

440

/**

441

* Set the integer value

442

* @param value New value

443

*/

444

public void setValue(long value);

445

446

@Override

447

public int intValue();

448

449

@Override

450

public long longValue();

451

452

@Override

453

public float floatValue();

454

455

@Override

456

public double doubleValue();

457

458

// Static utility methods

459

460

/**

461

* Compare two IntegerType values

462

* @param v1 First value

463

* @param v2 Second value

464

* @return Comparison result (-1, 0, 1)

465

*/

466

public static int compare(IntegerType v1, IntegerType v2);

467

}

468

469

/**

470

* Platform-specific long integer (long in C, not Java long)

471

*/

472

public class NativeLong extends IntegerType {

473

/** Size of native long in bytes */

474

public static final int SIZE;

475

476

public NativeLong();

477

public NativeLong(long value);

478

}

479

480

// Custom integer types

481

public static class UInt32 extends IntegerType {

482

public UInt32() { super(4, true); } // 4-byte unsigned

483

public UInt32(long value) { super(4, value, true); }

484

}

485

486

public static class Int64 extends IntegerType {

487

public Int64() { super(8, false); } // 8-byte signed

488

public Int64(long value) { super(8, value, false); }

489

}

490

```

491

492

## Type Mapping System

493

494

```java { .api }

495

/**

496

* Interface for custom Java to native type conversion

497

*/

498

public interface NativeMapped {

499

/**

500

* Convert from native representation to Java object

501

* @param nativeValue Native value

502

* @param context Conversion context

503

* @return Java object

504

*/

505

Object fromNative(Object nativeValue, FromNativeContext context);

506

507

/**

508

* Convert Java object to native representation

509

* @return Native value

510

*/

511

Object toNative();

512

513

/**

514

* Get native type class

515

* @return Class representing native type

516

*/

517

Class<?> nativeType();

518

}

519

520

/**

521

* Provides type converters for automatic conversion

522

*/

523

public interface TypeMapper {

524

/**

525

* Get converter for native-to-Java conversion

526

* @param javaType Target Java type

527

* @return Converter or null if none available

528

*/

529

FromNativeConverter getFromNativeConverter(Class<?> javaType);

530

531

/**

532

* Get converter for Java-to-native conversion

533

* @param javaType Source Java type

534

* @return Converter or null if none available

535

*/

536

ToNativeConverter getToNativeConverter(Class<?> javaType);

537

}

538

539

/**

540

* Default TypeMapper implementation

541

*/

542

public class DefaultTypeMapper implements TypeMapper {

543

/**

544

* Add bidirectional type converter

545

* @param javaType Java type to convert

546

* @param converter Bidirectional converter

547

*/

548

public void addTypeConverter(Class<?> javaType, TypeConverter converter);

549

550

/**

551

* Add from-native converter

552

* @param javaType Target Java type

553

* @param converter From-native converter

554

*/

555

public void addFromNativeConverter(Class<?> javaType, FromNativeConverter converter);

556

557

/**

558

* Add to-native converter

559

* @param javaType Source Java type

560

* @param converter To-native converter

561

*/

562

public void addToNativeConverter(Class<?> javaType, ToNativeConverter converter);

563

}

564

```

565

566

## Custom Type Examples

567

568

```java { .api }

569

// Boolean type that maps to int (common in C)

570

public static class CBoolean implements NativeMapped {

571

private final boolean value;

572

573

public CBoolean(boolean value) {

574

this.value = value;

575

}

576

577

public boolean booleanValue() {

578

return value;

579

}

580

581

@Override

582

public Object fromNative(Object nativeValue, FromNativeContext context) {

583

return new CBoolean(((Integer) nativeValue) != 0);

584

}

585

586

@Override

587

public Object toNative() {

588

return value ? 1 : 0;

589

}

590

591

@Override

592

public Class<?> nativeType() {

593

return Integer.class;

594

}

595

}

596

597

// Enum mapping to native constants

598

public enum Status implements NativeMapped {

599

OK(0), ERROR(1), PENDING(2);

600

601

private final int value;

602

603

Status(int value) {

604

this.value = value;

605

}

606

607

public int getValue() {

608

return value;

609

}

610

611

@Override

612

public Object fromNative(Object nativeValue, FromNativeContext context) {

613

int val = (Integer) nativeValue;

614

for (Status status : values()) {

615

if (status.value == val) return status;

616

}

617

throw new IllegalArgumentException("Invalid status: " + val);

618

}

619

620

@Override

621

public Object toNative() {

622

return value;

623

}

624

625

@Override

626

public Class<?> nativeType() {

627

return Integer.class;

628

}

629

}

630

631

// Using custom types in library interface

632

public interface MyLibrary extends Library {

633

void setEnabled(CBoolean enabled); // Converts boolean <-> int

634

Status getStatus(); // Converts int <-> Status enum

635

}

636

```

637

638

## Callback System

639

640

```java { .api }

641

/**

642

* Base interface for all native callbacks

643

*/

644

public interface Callback {

645

/** Default method name for single-method callbacks */

646

String METHOD_NAME = "callback";

647

648

/** Forbidden method names that cannot be callback methods */

649

String[] FORBIDDEN_NAMES = {"hashCode", "equals", "toString"};

650

651

/**

652

* Handler for uncaught exceptions in callback threads

653

*/

654

public interface UncaughtExceptionHandler {

655

void uncaughtException(Callback c, Throwable e);

656

}

657

}

658

659

// Simple callback examples

660

public interface SimpleCallback extends Callback {

661

void callback(int value);

662

}

663

664

public interface ComparisonCallback extends Callback {

665

int compare(Pointer a, Pointer b);

666

}

667

668

// Multi-method callback (must use METHOD_NAME)

669

public interface FileCallback extends Callback {

670

boolean callback(String filename, int attributes);

671

}

672

```

673

674

## Callback Usage Examples

675

676

```java { .api }

677

// Define library with callback functions

678

public interface CallbackLibrary extends Library {

679

CallbackLibrary INSTANCE = Native.loadLibrary("mylib", CallbackLibrary.class);

680

681

/**

682

* Register callback for notifications

683

* void setNotificationCallback(void (*callback)(int));

684

*/

685

void setNotificationCallback(SimpleCallback callback);

686

687

/**

688

* Sort array using comparison function

689

* void qsort(void* base, size_t num, size_t size,

690

* int (*compar)(const void*, const void*));

691

*/

692

void qsort(Pointer array, int count, int elementSize, ComparisonCallback comparator);

693

694

/**

695

* Enumerate files with callback

696

* int enumFiles(const char* path, bool (*callback)(const char*, int));

697

*/

698

int enumFiles(String path, FileCallback callback);

699

}

700

701

// Implement callbacks

702

SimpleCallback notifier = new SimpleCallback() {

703

@Override

704

public void callback(int value) {

705

System.out.println("Notification received: " + value);

706

}

707

};

708

709

ComparisonCallback intComparator = new ComparisonCallback() {

710

@Override

711

public int compare(Pointer a, Pointer b) {

712

int val1 = a.getInt(0);

713

int val2 = b.getInt(0);

714

return Integer.compare(val1, val2);

715

}

716

};

717

718

FileCallback fileHandler = new FileCallback() {

719

@Override

720

public boolean callback(String filename, int attributes) {

721

System.out.println("Found file: " + filename + " (attrs: " + attributes + ")");

722

return true; // Continue enumeration

723

}

724

};

725

726

// Register and use callbacks

727

CallbackLibrary.INSTANCE.setNotificationCallback(notifier);

728

729

// Sort integer array

730

Memory intArray = new Memory(40); // 10 integers

731

for (int i = 0; i < 10; i++) {

732

intArray.setInt(i * 4, (int)(Math.random() * 100));

733

}

734

CallbackLibrary.INSTANCE.qsort(intArray, 10, 4, intComparator);

735

736

// Enumerate files

737

CallbackLibrary.INSTANCE.enumFiles("/path/to/directory", fileHandler);

738

```

739

740

## Advanced Callback Features

741

742

```java { .api }

743

/**

744

* Callback thread initialization

745

*/

746

public class CallbackThreadInitializer {

747

/**

748

* Get thread name for callback

749

* @param cb Callback instance

750

* @return Thread name

751

*/

752

public String getName(Callback cb);

753

754

/**

755

* Get thread group for callback

756

* @param cb Callback instance

757

* @return Thread group

758

*/

759

public ThreadGroup getGroup(Callback cb);

760

761

/**

762

* Check if callback thread should be daemon

763

* @param cb Callback instance

764

* @return true if daemon thread

765

*/

766

public boolean isDaemon(Callback cb);

767

768

/**

769

* Get uncaught exception handler

770

* @param cb Callback instance

771

* @return Exception handler

772

*/

773

public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler(Callback cb);

774

}

775

776

// Callback with exception handling

777

SimpleCallback robustCallback = new SimpleCallback() {

778

@Override

779

public void callback(int value) {

780

try {

781

// Process value...

782

if (value < 0) {

783

throw new IllegalArgumentException("Negative value not allowed");

784

}

785

System.out.println("Processing: " + value);

786

} catch (Exception e) {

787

System.err.println("Callback error: " + e.getMessage());

788

// Don't let exceptions propagate to native code

789

}

790

}

791

};

792

```

793

794

## Function Pointer Management

795

796

```java { .api }

797

/**

798

* Manages callback references and function pointers

799

*/

800

public class CallbackReference extends WeakReference<Callback> {

801

/**

802

* Get callback instance from function pointer

803

* @param type Callback interface type

804

* @param p Function pointer

805

* @return Callback instance or null

806

*/

807

public static Callback getCallback(Class<?> type, Pointer p);

808

809

/**

810

* Get function pointer for callback

811

* @param callback Callback instance

812

* @return Native function pointer

813

*/

814

public static Pointer getFunctionPointer(Callback callback);

815

}

816

817

// Get function pointer for callback

818

Pointer funcPtr = CallbackReference.getFunctionPointer(myCallback);

819

820

// Pass function pointer directly to native code

821

someNativeFunction(funcPtr);

822

823

// Retrieve callback from pointer (if needed)

824

Callback retrieved = CallbackReference.getCallback(SimpleCallback.class, funcPtr);

825

```

826

827

## Structure Arrays and Complex Layouts

828

829

```java { .api }

830

// Array of structures

831

Point[] pointArray = (Point[]) new Point().toArray(10);

832

for (int i = 0; i < pointArray.length; i++) {

833

pointArray[i].x = i * 10;

834

pointArray[i].y = i * 20;

835

}

836

Structure.autoWrite(pointArray); // Write all structures

837

838

// Pass to native function expecting Point*

839

void processPoints(Point[] points);

840

841

// After native call, read updated values

842

Structure.autoRead(pointArray);

843

844

// Nested structures

845

public static class Rectangle extends Structure {

846

public Point topLeft = new Point();

847

public Point bottomRight = new Point();

848

849

@Override

850

protected List<String> getFieldOrder() {

851

return Arrays.asList("topLeft", "bottomRight");

852

}

853

}

854

855

// Variable-length structure (common C pattern)

856

public static class VariableStruct extends Structure {

857

public int count;

858

public int[] data;

859

860

public VariableStruct(int count) {

861

this.count = count;

862

this.data = new int[count];

863

}

864

865

@Override

866

protected List<String> getFieldOrder() {

867

return Arrays.asList("count", "data");

868

}

869

}

870

```

871

872

## Best Practices and Error Handling

873

874

```java { .api }

875

// Always implement getFieldOrder()

876

@Override

877

protected List<String> getFieldOrder() {

878

return Arrays.asList("field1", "field2", "field3");

879

// Order MUST match C structure layout

880

}

881

882

// Handle encoding for string fields

883

public static class TextStruct extends Structure {

884

public String text;

885

886

public TextStruct() {

887

super();

888

setStringEncoding("UTF-8"); // Explicit encoding

889

}

890

}

891

892

// Validate structure after read

893

@Override

894

public void read() {

895

super.read();

896

897

// Validate field values

898

if (count < 0 || count > MAX_COUNT) {

899

throw new IllegalStateException("Invalid count: " + count);

900

}

901

902

// Null-check string fields

903

if (name == null) {

904

name = "";

905

}

906

}

907

908

// Handle memory alignment issues

909

public static class AlignedStruct extends Structure {

910

public byte b; // 1 byte

911

// 3 bytes padding

912

public int i; // 4 bytes

913

public short s; // 2 bytes

914

// 2 bytes padding (to align to 4-byte boundary)

915

916

@Override

917

protected List<String> getFieldOrder() {

918

return Arrays.asList("b", "i", "s");

919

}

920

}

921

```

922

923

## WString Class - Wide Character String Support

924

925

The `WString` class provides Unicode wide character string support for native libraries:

926

927

```java { .api }

928

/**

929

* Wrapper for wide character strings (wchar_t* in C)

930

*/

931

public final class WString implements CharSequence, Comparable {

932

/**

933

* Create wide string from regular string

934

* @param s String to wrap

935

*/

936

public WString(String s);

937

938

// CharSequence implementation

939

public int length();

940

public char charAt(int index);

941

public CharSequence subSequence(int start, int end);

942

943

// String operations

944

public String toString();

945

public boolean equals(Object o);

946

public int hashCode();

947

public int compareTo(Object o);

948

}

949

```

950

951

### WString Usage Examples

952

953

```java

954

// Use WString for wide character APIs

955

public interface UnicodeAPI extends Library {

956

UnicodeAPI INSTANCE = Native.loadLibrary("mylib", UnicodeAPI.class);

957

958

/**

959

* Process wide character string

960

* @param text Wide character string input

961

* @return Length of processed string

962

*/

963

int processWideString(WString text);

964

965

/**

966

* Create wide character string

967

* @param buffer Buffer to fill with wide string

968

* @param maxLen Maximum length

969

* @return Actual length

970

*/

971

int createWideString(WString buffer, int maxLen);

972

}

973

974

// Usage

975

WString wideText = new WString("Hello Unicode: ñáéíóú");

976

int result = UnicodeAPI.INSTANCE.processWideString(wideText);

977

978

// Wide strings work with Windows APIs

979

Function messageBoxW = Function.getFunction("user32", "MessageBoxW", Function.ALT_CONVENTION);

980

messageBoxW.invoke(Integer.class, new Object[]{

981

Pointer.NULL, new WString("Unicode Message"), new WString("Title"), 0

982

});

983

```

984

985

## StringArray Class - Native String Arrays

986

987

The `StringArray` class manages native arrays of string pointers with automatic cleanup:

988

989

```java { .api }

990

/**

991

* Handle native array of char* or wchar_t* with automatic memory management

992

*/

993

public class StringArray extends Memory implements Function.PostCallRead {

994

/**

995

* Create native array of strings

996

* @param strings Java string array

997

*/

998

public StringArray(String[] strings);

999

1000

/**

1001

* Create wide character string array

1002

* @param strings Java string array

1003

* @param wide true for wide character strings

1004

*/

1005

public StringArray(String[] strings, boolean wide);

1006

1007

/**

1008

* Create string array with specific encoding

1009

* @param strings Java string array

1010

* @param encoding Character encoding

1011

*/

1012

public StringArray(String[] strings, String encoding);

1013

1014

/**

1015

* Create from WString array

1016

* @param strings WString array

1017

*/

1018

public StringArray(WString[] strings);

1019

1020

/**

1021

* Get updated string values after native call

1022

* @return String array with current values

1023

*/

1024

public String[] getStrings();

1025

1026

// PostCallRead implementation

1027

public void read();

1028

}

1029

```

1030

1031

### StringArray Usage Examples

1032

1033

```java

1034

// Native function expecting char** array

1035

public interface SystemAPI extends Library {

1036

SystemAPI INSTANCE = Native.loadLibrary("system", SystemAPI.class);

1037

1038

/**

1039

* Execute command with arguments

1040

* @param command Command name

1041

* @param args Null-terminated argument array

1042

* @return Exit code

1043

*/

1044

int execv(String command, StringArray args);

1045

1046

/**

1047

* Process environment variables

1048

* @param envVars Environment variable array

1049

*/

1050

void processEnvironment(StringArray envVars);

1051

}

1052

1053

// Usage

1054

String[] cmdArgs = {"/bin/ls", "-la", "/tmp", null}; // NULL-terminated

1055

StringArray nativeArgs = new StringArray(cmdArgs);

1056

1057

int exitCode = SystemAPI.INSTANCE.execv("/bin/ls", nativeArgs);

1058

1059

// Wide character string arrays for Windows

1060

String[] paths = {"C:\\Program Files", "C:\\Windows", "C:\\Users"};

1061

StringArray widePaths = new StringArray(paths, true); // Wide strings

1062

1063

// String array with custom encoding

1064

String[] utf8Strings = {"ñáéíóú", "中文", "العربية"};

1065

StringArray encodedStrings = new StringArray(utf8Strings, "UTF-8");

1066

```

1067

1068

## Type Conversion System

1069

1070

### TypeMapper Interface - Custom Type Conversion

1071

1072

```java { .api }

1073

/**

1074

* Provides converters for Java to native type conversion

1075

*/

1076

public interface TypeMapper {

1077

/**

1078

* Get converter from native to Java type

1079

* @param javaType Target Java type

1080

* @return Converter from native type

1081

*/

1082

FromNativeConverter getFromNativeConverter(Class<?> javaType);

1083

1084

/**

1085

* Get converter from Java to native type

1086

* @param javaType Source Java type

1087

* @return Converter to native type

1088

*/

1089

ToNativeConverter getToNativeConverter(Class<?> javaType);

1090

}

1091

```

1092

1093

### NativeMapped Interface - Bidirectional Type Conversion

1094

1095

```java { .api }

1096

/**

1097

* Interface for objects that can convert between Java and native types

1098

*/

1099

public interface NativeMapped {

1100

/**

1101

* Convert from native value to Java object

1102

* @param nativeValue Native value to convert

1103

* @param context Conversion context

1104

* @return Java object representation

1105

*/

1106

Object fromNative(Object nativeValue, FromNativeContext context);

1107

1108

/**

1109

* Convert this object to native value

1110

* @return Native representation

1111

*/

1112

Object toNative();

1113

1114

/**

1115

* Get the native type used for conversion

1116

* @return Native type class

1117

*/

1118

Class<?> nativeType();

1119

}

1120

```

1121

1122

### Custom Type Conversion Examples

1123

1124

```java

1125

// Custom enum with native mapping

1126

public enum Color implements NativeMapped {

1127

RED(1), GREEN(2), BLUE(3);

1128

1129

private final int value;

1130

1131

Color(int value) {

1132

this.value = value;

1133

}

1134

1135

@Override

1136

public Object toNative() {

1137

return value;

1138

}

1139

1140

@Override

1141

public Object fromNative(Object nativeValue, FromNativeContext context) {

1142

int val = (Integer) nativeValue;

1143

for (Color color : values()) {

1144

if (color.value == val) return color;

1145

}

1146

throw new IllegalArgumentException("Unknown color: " + val);

1147

}

1148

1149

@Override

1150

public Class<?> nativeType() {

1151

return Integer.class;

1152

}

1153

}

1154

1155

// TypeMapper for custom conversions

1156

public class CustomTypeMapper implements TypeMapper {

1157

@Override

1158

public FromNativeConverter getFromNativeConverter(Class<?> javaType) {

1159

if (javaType == Color.class) {

1160

return new FromNativeConverter() {

1161

@Override

1162

public Object fromNative(Object nativeValue, FromNativeContext context) {

1163

return Color.values()[(Integer) nativeValue - 1];

1164

}

1165

1166

@Override

1167

public Class<?> nativeType() {

1168

return Integer.class;

1169

}

1170

};

1171

}

1172

return null;

1173

}

1174

1175

@Override

1176

public ToNativeConverter getToNativeConverter(Class<?> javaType) {

1177

if (javaType == Color.class) {

1178

return new ToNativeConverter() {

1179

@Override

1180

public Object toNative(Object value, ToNativeContext context) {

1181

return ((Color) value).value;

1182

}

1183

1184

@Override

1185

public Class<?> nativeType() {

1186

return Integer.class;

1187

}

1188

};

1189

}

1190

return null;

1191

}

1192

}

1193

1194

// Use custom type mapper in library

1195

Map<String, Object> options = new HashMap<>();

1196

options.put(Library.OPTION_TYPE_MAPPER, new CustomTypeMapper());

1197

1198

MyLibrary lib = Native.loadLibrary("mylib", MyLibrary.class, options);

1199

1200

// Now Color enum works automatically

1201

Color result = lib.getPreferredColor(); // Returns Color enum

1202

lib.setBackgroundColor(Color.BLUE); // Accepts Color enum

1203

```

1204

1205

This comprehensive type system enables seamless integration between Java objects and native data structures, providing automatic memory layout, type conversion, and callback support for complex native library integration.