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.