or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

exceptions.mdindex.mdinitialization.mdmemory-management.mdmodules.mdobjects.mdutilities.md

utilities.mddocs/

0

# Utility Functions and Helpers

1

2

Additional utilities including buffer protocol, callable objects, threading and GIL management, type system operations, and various helper functions for advanced Python integration scenarios.

3

4

## Capabilities

5

6

### Buffer Protocol

7

8

Python's buffer protocol for efficient access to memory buffers and array-like objects.

9

10

```java { .api }

11

/**

12

* Get buffer view of an object

13

* @param obj - Object to get buffer from

14

* @param view - Buffer view structure to fill

15

* @param flags - Buffer access flags

16

* @return 0 on success, -1 on error

17

*/

18

public static native int PyObject_GetBuffer(PyObject obj, Py_buffer view, int flags);

19

20

/**

21

* Release buffer view

22

* @param view - Buffer view to release

23

*/

24

public static native void PyBuffer_Release(Py_buffer view);

25

26

/**

27

* Get pointer to specific location in buffer

28

* @param view - Buffer view

29

* @param indices - Index array for multidimensional access

30

* @return Pointer to buffer location

31

*/

32

public static native Pointer PyBuffer_GetPointer(Py_buffer view, SizeTPointer indices);

33

34

/**

35

* Copy buffer data to contiguous memory

36

* @param buf - Destination buffer

37

* @param view - Source buffer view

38

* @param len - Number of bytes to copy

39

* @param order - Memory order ('C' or 'F')

40

* @return 0 on success, -1 on error

41

*/

42

public static native int PyBuffer_ToContiguous(Pointer buf, Py_buffer view, long len, char order);

43

44

/**

45

* Copy contiguous data to buffer

46

* @param view - Destination buffer view

47

* @param buf - Source buffer

48

* @param len - Number of bytes to copy

49

* @param order - Memory order ('C' or 'F')

50

* @return 0 on success, -1 on error

51

*/

52

public static native int PyBuffer_FromContiguous(Py_buffer view, Pointer buf, long len, char order);

53

54

/**

55

* Check if buffer is contiguous

56

* @param view - Buffer view

57

* @param order - Memory order to check ('C', 'F', or 'A')

58

* @return 1 if contiguous, 0 otherwise

59

*/

60

public static native int PyBuffer_IsContiguous(Py_buffer view, char order);

61

62

/**

63

* Fill buffer info structure

64

* @param view - Buffer view to fill

65

* @param obj - Object owning the buffer

66

* @param buf - Buffer pointer

67

* @param len - Buffer length

68

* @param readonly - 1 if read-only, 0 if writable

69

* @param flags - Buffer flags

70

* @return 0 on success, -1 on error

71

*/

72

public static native int PyBuffer_FillInfo(Py_buffer view, PyObject obj, Pointer buf,

73

long len, int readonly, int flags);

74

```

75

76

**Usage Example:**

77

78

```java

79

import static org.bytedeco.cpython.global.python.*;

80

81

// Get buffer from bytes object

82

PyObject bytesObj = PyBytes_FromString("Hello World");

83

Py_buffer buffer = new Py_buffer();

84

85

int result = PyObject_GetBuffer(bytesObj, buffer, PyBUF_SIMPLE);

86

if (result == 0) {

87

try {

88

// Access buffer data

89

Pointer data = buffer.buf();

90

long length = buffer.len();

91

92

System.out.println("Buffer length: " + length);

93

94

// Copy to contiguous memory

95

Pointer contiguous = PyMem_Malloc(length);

96

PyBuffer_ToContiguous(contiguous, buffer, length, 'C');

97

98

// Use contiguous data...

99

100

PyMem_Free(contiguous);

101

102

} finally {

103

// Always release buffer

104

PyBuffer_Release(buffer);

105

}

106

}

107

```

108

109

### Code Execution and Evaluation

110

111

Essential functions for executing Python code, evaluating expressions, and compiling Python source code from Java applications.

112

113

```java { .api }

114

/**

115

* Execute Python source code string (equivalent to exec())

116

* @param command - Python code string to execute

117

* @return 0 on success, -1 on error

118

*/

119

public static native int PyRun_SimpleString(String command);

120

121

/**

122

* Execute Python source with error checking

123

* @param command - Python code string to execute

124

* @return 0 on success, -1 on error (with exception set)

125

*/

126

public static native int PyRun_SimpleStringFlags(String command, PyCompilerFlags flags);

127

128

/**

129

* Execute Python source code in specified namespace

130

* @param str - Python code string

131

* @param start - Start symbol (Py_eval_input, Py_single_input, or Py_file_input)

132

* @param globals - Global namespace dictionary

133

* @param locals - Local namespace dictionary

134

* @return Result object, or NULL on error

135

*/

136

public static native PyObject PyRun_String(String str, int start, PyObject globals, PyObject locals);

137

138

/**

139

* Execute Python source code with compiler flags

140

* @param str - Python code string

141

* @param start - Start symbol

142

* @param globals - Global namespace dictionary

143

* @param locals - Local namespace dictionary

144

* @param flags - Compiler flags

145

* @return Result object, or NULL on error

146

*/

147

public static native PyObject PyRun_StringFlags(String str, int start, PyObject globals,

148

PyObject locals, PyCompilerFlags flags);

149

150

/**

151

* Execute Python file from FILE pointer

152

* @param file - Open FILE pointer to Python source

153

* @param filename - Filename for error reporting

154

* @param start - Start symbol

155

* @param globals - Global namespace dictionary

156

* @param locals - Local namespace dictionary

157

* @return Result object, or NULL on error

158

*/

159

public static native PyObject PyRun_File(Pointer file, String filename, int start,

160

PyObject globals, PyObject locals);

161

162

/**

163

* Compile Python source code to code object

164

* @param str - Python source code string

165

* @param filename - Filename for error reporting

166

* @param start - Start symbol (Py_eval_input, Py_single_input, or Py_file_input)

167

* @return Compiled code object, or NULL on error

168

*/

169

public static native PyObject Py_CompileString(String str, String filename, int start);

170

171

/**

172

* Compile Python source with compiler flags

173

* @param str - Python source code string

174

* @param filename - Filename for error reporting

175

* @param start - Start symbol

176

* @param flags - Compiler flags

177

* @return Compiled code object, or NULL on error

178

*/

179

public static native PyObject Py_CompileStringFlags(String str, String filename, int start,

180

PyCompilerFlags flags);

181

182

/**

183

* Evaluate compiled code object

184

* @param code - Compiled code object

185

* @param globals - Global namespace dictionary

186

* @param locals - Local namespace dictionary

187

* @return Result object, or NULL on error

188

*/

189

public static native PyObject PyEval_EvalCode(PyObject code, PyObject globals, PyObject locals);

190

191

/**

192

* Evaluate code object with additional parameters

193

* @param code - Compiled code object

194

* @param globals - Global namespace dictionary

195

* @param locals - Local namespace dictionary

196

* @param args - Positional arguments array

197

* @param argcount - Number of positional arguments

198

* @param kwds - Keyword arguments array

199

* @param kwdcount - Number of keyword arguments

200

* @param defs - Default argument values

201

* @param defcount - Number of default values

202

* @param closure - Closure tuple for nested functions

203

* @return Result object, or NULL on error

204

*/

205

public static native PyObject PyEval_EvalCodeEx(PyObject code, PyObject globals, PyObject locals,

206

PointerPointer args, int argcount,

207

PointerPointer kwds, int kwdcount,

208

PointerPointer defs, int defcount,

209

PyObject closure);

210

```

211

212

**Execution Start Symbols:**

213

214

```java { .api }

215

// Execution mode constants

216

public static final int Py_single_input = 256; // Single interactive statement

217

public static final int Py_file_input = 257; // Complete Python file

218

public static final int Py_eval_input = 258; // Single expression for evaluation

219

```

220

221

**Usage Examples:**

222

223

```java

224

import static org.bytedeco.cpython.global.python.*;

225

226

// Simple code execution

227

PyRun_SimpleString("print('Hello from Python!')");

228

PyRun_SimpleString("x = 42; print(f'The answer is {x}')");

229

230

// Execute code with result capture

231

PyObject globals = PyDict_New();

232

PyObject locals = PyDict_New();

233

234

// Execute statements

235

PyRun_String("x = 10; y = 20", Py_file_input, globals, locals);

236

237

// Evaluate expression

238

PyObject result = PyRun_String("x + y", Py_eval_input, globals, locals);

239

long sum = PyLong_AsLong(result); // 30

240

241

// Compile and execute separately

242

PyObject code = Py_CompileString("result = x * y", "calculation", Py_file_input);

243

if (code != null) {

244

PyEval_EvalCode(code, globals, locals);

245

246

// Get result from locals

247

PyObject pyResult = PyDict_GetItemString(locals, "result");

248

long product = PyLong_AsLong(pyResult); // 200

249

}

250

251

// Execute Python file content

252

String pythonScript = """

253

def fibonacci(n):

254

if n <= 1:

255

return n

256

return fibonacci(n-1) + fibonacci(n-2)

257

258

result = fibonacci(10)

259

""";

260

261

PyRun_String(pythonScript, Py_file_input, globals, locals);

262

PyObject fibResult = PyDict_GetItemString(locals, "result");

263

System.out.println("Fibonacci(10) = " + PyLong_AsLong(fibResult)); // 55

264

```

265

266

### Callable Objects and Functions

267

268

Functions for working with callable Python objects and function calls.

269

270

```java { .api }

271

/**

272

* Check if object is callable

273

* @param obj - Object to check

274

* @return 1 if callable, 0 otherwise

275

*/

276

public static native int PyCallable_Check(PyObject obj);

277

278

/**

279

* Call callable object with arguments and keywords

280

* @param callable - Callable object

281

* @param args - Tuple of positional arguments

282

* @param kwargs - Dictionary of keyword arguments (or NULL)

283

* @return Result of call, or NULL on error

284

*/

285

public static native PyObject PyObject_Call(PyObject callable, PyObject args, PyObject kwargs);

286

287

/**

288

* Call callable object with tuple of arguments

289

* @param callable - Callable object

290

* @param args - Tuple of arguments (or NULL for no args)

291

* @return Result of call, or NULL on error

292

*/

293

public static native PyObject PyObject_CallObject(PyObject callable, PyObject args);

294

295

/**

296

* Call callable with formatted arguments

297

* @param callable - Callable object

298

* @param format - Argument format string

299

* @param args - Arguments matching format

300

* @return Result of call, or NULL on error

301

*/

302

public static native PyObject PyObject_CallFunction(PyObject callable, String format, Object... args);

303

304

/**

305

* Call method on object with formatted arguments

306

* @param obj - Object to call method on

307

* @param method - Method name

308

* @param format - Argument format string

309

* @param args - Arguments matching format

310

* @return Result of call, or NULL on error

311

*/

312

public static native PyObject PyObject_CallMethod(PyObject obj, String method, String format, Object... args);

313

```

314

315

### Vectorcall Protocol (Fast Calling)

316

317

High-performance calling protocol introduced in Python 3.8+.

318

319

```java { .api }

320

/**

321

* Call using vectorcall protocol

322

* @param callable - Callable object

323

* @param args - Array of argument objects

324

* @param nargsf - Number of arguments (with flags)

325

* @param kwnames - Tuple of keyword names (or NULL)

326

* @return Result of call, or NULL on error

327

*/

328

public static native PyObject PyObject_Vectorcall(PyObject callable, PointerPointer args,

329

long nargsf, PyObject kwnames);

330

331

/**

332

* Call using vectorcall with dictionary keywords

333

* @param callable - Callable object

334

* @param args - Array of argument objects

335

* @param nargsf - Number of arguments (with flags)

336

* @param kwargs - Dictionary of keyword arguments

337

* @return Result of call, or NULL on error

338

*/

339

public static native PyObject PyObject_VectorcallDict(PyObject callable, PointerPointer args,

340

long nargsf, PyObject kwargs);

341

342

/**

343

* Check if object supports vectorcall

344

* @param callable - Object to check

345

* @return 1 if supports vectorcall, 0 otherwise

346

*/

347

public static native int PyVectorcall_NARGS(long nargsf);

348

```

349

350

**Usage Example:**

351

352

```java

353

// Call a Python function

354

PyObject func = PyObject_GetAttrString(module, "my_function");

355

356

if (PyCallable_Check(func) != 0) {

357

// Create arguments tuple

358

PyObject args = PyTuple_New(2);

359

PyTuple_SetItem(args, 0, PyLong_FromLong(10));

360

PyTuple_SetItem(args, 1, PyUnicode_FromString("test"));

361

362

// Call function

363

PyObject result = PyObject_CallObject(func, args);

364

365

if (result != null) {

366

// Process result

367

System.out.println("Function returned: " + result);

368

} else {

369

PyErr_Clear();

370

}

371

}

372

373

// Call method on object

374

PyObject obj = getMyObject();

375

PyObject methodResult = PyObject_CallMethod(obj, "process", "si", "data", 42);

376

```

377

378

### Threading and GIL Management

379

380

Functions for managing Python's Global Interpreter Lock (GIL) and thread state.

381

382

```java { .api }

383

/**

384

* Get thread state for current thread

385

* @return Thread state for this thread, or NULL if no Python thread state

386

*/

387

public static native PyThreadState PyGILState_GetThisThreadState();

388

389

/**

390

* Check if current thread holds the GIL

391

* @return 1 if GIL is held, 0 otherwise

392

*/

393

public static native int PyGILState_Check();

394

395

/**

396

* Ensure current thread has the GIL

397

* @return GIL state token (must be passed to PyGILState_Release)

398

*/

399

public static native @Cast("PyGILState_STATE") int PyGILState_Ensure();

400

401

/**

402

* Release GIL acquired with PyGILState_Ensure

403

* @param state - State token from PyGILState_Ensure

404

*/

405

public static native void PyGILState_Release(@Cast("PyGILState_STATE") int state);

406

407

/**

408

* Create new thread state for interpreter

409

* @param interp - Interpreter state

410

* @return New thread state

411

*/

412

public static native PyThreadState PyThreadState_New(PyInterpreterState interp);

413

414

/**

415

* Clear thread state (prepare for deletion)

416

* @param tstate - Thread state to clear

417

*/

418

public static native void PyThreadState_Clear(PyThreadState tstate);

419

420

/**

421

* Delete thread state

422

* @param tstate - Thread state to delete

423

*/

424

public static native void PyThreadState_Delete(PyThreadState tstate);

425

426

/**

427

* Get current thread state

428

* @return Current thread state

429

*/

430

public static native PyThreadState PyThreadState_Get();

431

432

/**

433

* Swap thread state (make different thread state current)

434

* @param tstate - New thread state (or NULL)

435

* @return Previous thread state

436

*/

437

public static native PyThreadState PyThreadState_Swap(PyThreadState tstate);

438

```

439

440

**Usage Example:**

441

442

```java

443

// Proper GIL management from Java thread

444

public class PythonWorker {

445

446

public void doWorkInPython() {

447

// Acquire GIL

448

int gilState = PyGILState_Ensure();

449

450

try {

451

// Now safe to call Python API

452

PyObject result = PyRun_SimpleString("print('Hello from Java thread')");

453

454

// More Python operations...

455

456

} finally {

457

// Always release GIL

458

PyGILState_Release(gilState);

459

}

460

}

461

462

public void longRunningTask() {

463

int gilState = PyGILState_Ensure();

464

465

try {

466

// Do some Python setup

467

PyObject data = PyList_New(1000000);

468

469

// Release GIL for long computation

470

PyGILState_Release(gilState);

471

gilState = null;

472

473

// Do Java computation without holding GIL

474

doExpensiveJavaComputation();

475

476

// Re-acquire GIL for Python work

477

gilState = PyGILState_Ensure();

478

479

// Continue with Python operations

480

PyList_Append(data, PyUnicode_FromString("done"));

481

482

} finally {

483

if (gilState != 0) {

484

PyGILState_Release(gilState);

485

}

486

}

487

}

488

489

private void doExpensiveJavaComputation() {

490

// Long-running Java code that doesn't need Python

491

// Good to release GIL during this

492

}

493

}

494

```

495

496

### Type System Operations

497

498

Advanced type system functions for working with Python types and classes.

499

500

```java { .api }

501

/**

502

* Prepare type object for use (must be called before using custom types)

503

* @param type - Type object to prepare

504

* @return 0 on success, -1 on error

505

*/

506

public static native int PyType_Ready(PyTypeObject type);

507

508

/**

509

* Create type from specification

510

* @param spec - Type specification structure

511

* @return New type object, or NULL on error

512

*/

513

public static native PyTypeObject PyType_FromSpec(PyType_Spec spec);

514

515

/**

516

* Create type from specification with base classes

517

* @param spec - Type specification

518

* @param bases - Tuple of base classes

519

* @return New type object, or NULL on error

520

*/

521

public static native PyTypeObject PyType_FromSpecWithBases(PyType_Spec spec, PyObject bases);

522

523

/**

524

* Create type from specification with module association

525

* @param module - Module to associate type with

526

* @param spec - Type specification

527

* @param bases - Tuple of base classes

528

* @return New type object, or NULL on error

529

*/

530

public static native PyTypeObject PyType_FromModuleAndSpec(PyObject module, PyType_Spec spec, PyObject bases);

531

532

/**

533

* Check if one type is subtype of another

534

* @param a - Potential subtype

535

* @param b - Potential base type

536

* @return 1 if a is subtype of b, 0 otherwise

537

*/

538

public static native int PyType_IsSubtype(PyTypeObject a, PyTypeObject b);

539

540

/**

541

* Check if object is instance of class

542

* @param obj - Object to check

543

* @param cls - Class to check against

544

* @return 1 if instance, 0 if not, -1 on error

545

*/

546

public static native int PyObject_IsInstance(PyObject obj, PyObject cls);

547

548

/**

549

* Check if one class is subclass of another

550

* @param derived - Potential subclass

551

* @param cls - Potential base class

552

* @return 1 if subclass, 0 if not, -1 on error

553

*/

554

public static native int PyObject_IsSubclass(PyObject derived, PyObject cls);

555

```

556

557

### Type Data Management

558

559

```java { .api }

560

/**

561

* Get size of type-specific data

562

* @param cls - Type object

563

* @return Size of type data in bytes

564

*/

565

public static native long PyType_GetTypeDataSize(PyTypeObject cls);

566

567

/**

568

* Get pointer to type-specific data

569

* @param cls - Type object

570

* @param base - Base type that defines the data

571

* @return Pointer to type data

572

*/

573

public static native Pointer PyType_GetTypeData(PyTypeObject cls, PyTypeObject base);

574

```

575

576

**Usage Example:**

577

578

```java

579

// Check types and inheritance

580

PyObject obj = getMyObject();

581

PyObject listType = PyList_Type(); // Assuming this exists

582

583

// Check if object is a list

584

if (PyObject_IsInstance(obj, listType) == 1) {

585

System.out.println("Object is a list");

586

}

587

588

// Check type inheritance

589

PyTypeObject customType = getCustomType();

590

if (PyType_IsSubtype(customType, listType) == 1) {

591

System.out.println("Custom type inherits from list");

592

}

593

```

594

595

### Mathematical and Utility Constants

596

597

Important constants for mathematical operations and system limits.

598

599

```java { .api }

600

/**

601

* Mathematical constants

602

*/

603

public static final double Py_MATH_PI = 3.14159265358979323846;

604

public static final double Py_MATH_E = 2.7182818284590452354;

605

public static final double Py_MATH_TAU = 6.2831853071795864769252867665590057683943;

606

607

/**

608

* Get positive infinity value

609

* @return Positive infinity as double

610

*/

611

public static native double Py_INFINITY();

612

613

/**

614

* Build and version constants

615

*/

616

public static final int Py_ENABLE_SHARED = 1;

617

public static final int Py_CAN_START_THREADS = 1;

618

```

619

620

### Advanced Object Operations

621

622

Additional object manipulation and introspection functions.

623

624

```java { .api }

625

/**

626

* Get object's string representation

627

* @param obj - Object to get representation of

628

* @return String representation, or NULL on error

629

*/

630

public static native PyObject PyObject_Str(PyObject obj);

631

632

/**

633

* Get object's printable representation

634

* @param obj - Object to get representation of

635

* @return Printable representation, or NULL on error

636

*/

637

public static native PyObject PyObject_Repr(PyObject obj);

638

639

/**

640

* Get object's ASCII representation

641

* @param obj - Object to get representation of

642

* @return ASCII representation, or NULL on error

643

*/

644

public static native PyObject PyObject_ASCII(PyObject obj);

645

646

/**

647

* Get object's bytes representation

648

* @param obj - Object to convert to bytes

649

* @return Bytes object, or NULL on error

650

*/

651

public static native PyObject PyObject_Bytes(PyObject obj);

652

653

/**

654

* Check if object is true in boolean context

655

* @param obj - Object to check

656

* @return 1 if true, 0 if false, -1 on error

657

*/

658

public static native int PyObject_IsTrue(PyObject obj);

659

660

/**

661

* Check if object is false in boolean context

662

* @param obj - Object to check

663

* @return 1 if false, 0 if true, -1 on error

664

*/

665

public static native int PyObject_IsFalse(PyObject obj);

666

667

/**

668

* Get length of object

669

* @param obj - Object to get length of

670

* @return Length, or -1 on error

671

*/

672

public static native long PyObject_Length(PyObject obj);

673

```

674

675

## Key Utility Types

676

677

```java { .api }

678

/**

679

* Buffer view structure for buffer protocol

680

*/

681

class Py_buffer extends Pointer {

682

// Contains:

683

// - buf: pointer to buffer data

684

// - len: length in bytes

685

// - readonly: read-only flag

686

// - format: format string

687

// - ndim: number of dimensions

688

// - shape: array of dimension sizes

689

// - strides: array of strides

690

// - suboffsets: suboffsets array

691

}

692

693

/**

694

* Type specification for creating new types

695

*/

696

class PyType_Spec extends Pointer {

697

// Contains:

698

// - name: type name

699

// - basicsize: basic instance size

700

// - itemsize: variable part size

701

// - flags: type flags

702

// - slots: array of slot definitions

703

}

704

705

/**

706

* GIL state enumeration (returned as int)

707

*/

708

public static final int PyGILState_STATE = 0; // Enum value cast to int

709

710

/**

711

* Thread state object

712

*/

713

class PyThreadState extends Pointer { }

714

715

/**

716

* Interpreter state object

717

*/

718

class PyInterpreterState extends Pointer { }

719

```

720

721

## Advanced Usage Patterns

722

723

### High-Performance Buffer Operations

724

725

```java

726

public class BufferOperations {

727

728

public static void processLargeArray(PyObject arrayObj) {

729

Py_buffer buffer = new Py_buffer();

730

731

if (PyObject_GetBuffer(arrayObj, buffer, PyBUF_C_CONTIGUOUS) == 0) {

732

try {

733

long itemCount = buffer.len() / buffer.itemsize();

734

735

// Check if contiguous for fast access

736

if (PyBuffer_IsContiguous(buffer, 'C') == 1) {

737

// Direct memory access for maximum performance

738

Pointer data = buffer.buf();

739

740

// Process data directly in native code

741

processNativeBuffer(data, itemCount);

742

} else {

743

// Copy to contiguous buffer first

744

Pointer contiguous = PyMem_Malloc(buffer.len());

745

PyBuffer_ToContiguous(contiguous, buffer, buffer.len(), 'C');

746

747

processNativeBuffer(contiguous, itemCount);

748

749

// Copy back if buffer is writable

750

if (buffer.readonly() == 0) {

751

PyBuffer_FromContiguous(buffer, contiguous, buffer.len(), 'C');

752

}

753

754

PyMem_Free(contiguous);

755

}

756

757

} finally {

758

PyBuffer_Release(buffer);

759

}

760

}

761

}

762

763

private static native void processNativeBuffer(Pointer data, long count);

764

}

765

```

766

767

### Thread Pool Integration

768

769

```java

770

public class PythonThreadPool {

771

772

private final ExecutorService executor;

773

774

public PythonThreadPool(int threadCount) {

775

this.executor = Executors.newFixedThreadPool(threadCount);

776

}

777

778

public CompletableFuture<PyObject> submitPythonTask(String pythonCode) {

779

return CompletableFuture.supplyAsync(() -> {

780

int gilState = PyGILState_Ensure();

781

782

try {

783

return PyRun_SimpleString(pythonCode);

784

} finally {

785

PyGILState_Release(gilState);

786

}

787

}, executor);

788

}

789

790

public void shutdown() {

791

executor.shutdown();

792

}

793

}

794

```

795

796

### Custom Type Creation

797

798

```java

799

public class CustomTypeBuilder {

800

801

public static PyTypeObject createCustomListType() {

802

// This is a simplified example - real type creation

803

// requires more detailed slot filling

804

805

PyType_Spec spec = new PyType_Spec();

806

// Fill spec with type information

807

// spec.name = "CustomList"

808

// spec.basicsize = sizeof(CustomListObject)

809

// spec.flags = Py_TPFLAGS_DEFAULT

810

811

PyTypeObject newType = PyType_FromSpec(spec);

812

813

if (newType != null) {

814

// Prepare the type for use

815

if (PyType_Ready(newType) < 0) {

816

return null;

817

}

818

}

819

820

return newType;

821

}

822

}

823

```

824

825

## Performance Optimization Tips

826

827

### Efficient Function Calling

828

829

```java

830

// Use vectorcall for better performance when available

831

if (supportsVectorcall(func)) {

832

PointerPointer args = new PointerPointer(argArray);

833

PyObject result = PyObject_Vectorcall(func, args, argCount, null);

834

} else {

835

// Fall back to traditional calling

836

PyObject argTuple = createArgTuple(argArray);

837

PyObject result = PyObject_CallObject(func, argTuple);

838

}

839

```

840

841

### Buffer Protocol Optimization

842

843

```java

844

// Request specific buffer format for optimal performance

845

int flags = PyBUF_C_CONTIGUOUS | PyBUF_FORMAT;

846

if (PyObject_GetBuffer(obj, buffer, flags) == 0) {

847

// Got optimal buffer format

848

} else {

849

// Fall back to simple buffer

850

PyErr_Clear();

851

PyObject_GetBuffer(obj, buffer, PyBUF_SIMPLE);

852

}

853

```

854

855

### GIL Management Best Practices

856

857

```java

858

// Minimize GIL hold time

859

int gilState = PyGILState_Ensure();

860

PyObject data = extractPythonData(); // Quick Python operation

861

PyGILState_Release(gilState);

862

863

// Do heavy computation without GIL

864

Object processedData = processInJava(data);

865

866

// Re-acquire GIL for final Python operations

867

gilState = PyGILState_Ensure();

868

storePythonResult(processedData);

869

PyGILState_Release(gilState);

870

```

871

872

## Important Notes

873

874

### Thread Safety

875

876

- Always use GIL management when calling from multiple Java threads

877

- Buffer protocol operations are not thread-safe without proper locking

878

- Type creation should be done during initialization, not from multiple threads

879

880

### Memory Management

881

882

- Always release buffers with `PyBuffer_Release()`

883

- GIL state tokens must be properly matched with `PyGILState_Release()`

884

- Custom types require careful reference counting

885

886

### Performance Considerations

887

888

- Vectorcall protocol provides significant performance benefits for frequent function calls

889

- Contiguous buffers allow for maximum performance in data processing

890

- Minimize GIL acquire/release cycles for better concurrency

891

892

### Error Handling

893

894

Most utility functions follow standard Python C API error conventions - check return values and `PyErr_Occurred()` for error detection.