CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-bytedeco--cpython

JavaCPP bindings for CPython 3.13.5 enabling Java applications to embed Python interpreters and interact with Python objects through the Python C API

Pending
Overview
Eval results
Files

utilities.mddocs/

Utility Functions and Helpers

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

Capabilities

Buffer Protocol

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

/**
 * Get buffer view of an object
 * @param obj - Object to get buffer from
 * @param view - Buffer view structure to fill
 * @param flags - Buffer access flags
 * @return 0 on success, -1 on error
 */
public static native int PyObject_GetBuffer(PyObject obj, Py_buffer view, int flags);

/**
 * Release buffer view
 * @param view - Buffer view to release
 */
public static native void PyBuffer_Release(Py_buffer view);

/**
 * Get pointer to specific location in buffer
 * @param view - Buffer view
 * @param indices - Index array for multidimensional access
 * @return Pointer to buffer location
 */
public static native Pointer PyBuffer_GetPointer(Py_buffer view, SizeTPointer indices);

/**
 * Copy buffer data to contiguous memory
 * @param buf - Destination buffer
 * @param view - Source buffer view
 * @param len - Number of bytes to copy
 * @param order - Memory order ('C' or 'F')
 * @return 0 on success, -1 on error
 */
public static native int PyBuffer_ToContiguous(Pointer buf, Py_buffer view, long len, char order);

/**
 * Copy contiguous data to buffer
 * @param view - Destination buffer view
 * @param buf - Source buffer  
 * @param len - Number of bytes to copy
 * @param order - Memory order ('C' or 'F')
 * @return 0 on success, -1 on error
 */
public static native int PyBuffer_FromContiguous(Py_buffer view, Pointer buf, long len, char order);

/**
 * Check if buffer is contiguous
 * @param view - Buffer view
 * @param order - Memory order to check ('C', 'F', or 'A')
 * @return 1 if contiguous, 0 otherwise
 */
public static native int PyBuffer_IsContiguous(Py_buffer view, char order);

/**
 * Fill buffer info structure
 * @param view - Buffer view to fill
 * @param obj - Object owning the buffer
 * @param buf - Buffer pointer
 * @param len - Buffer length
 * @param readonly - 1 if read-only, 0 if writable
 * @param flags - Buffer flags
 * @return 0 on success, -1 on error
 */
public static native int PyBuffer_FillInfo(Py_buffer view, PyObject obj, Pointer buf, 
                                         long len, int readonly, int flags);

Usage Example:

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

// Get buffer from bytes object
PyObject bytesObj = PyBytes_FromString("Hello World");
Py_buffer buffer = new Py_buffer();

int result = PyObject_GetBuffer(bytesObj, buffer, PyBUF_SIMPLE);
if (result == 0) {
    try {
        // Access buffer data
        Pointer data = buffer.buf();
        long length = buffer.len();
        
        System.out.println("Buffer length: " + length);
        
        // Copy to contiguous memory
        Pointer contiguous = PyMem_Malloc(length);
        PyBuffer_ToContiguous(contiguous, buffer, length, 'C');
        
        // Use contiguous data...
        
        PyMem_Free(contiguous);
        
    } finally {
        // Always release buffer
        PyBuffer_Release(buffer);
    }
}

Code Execution and Evaluation

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

/**
 * Execute Python source code string (equivalent to exec())
 * @param command - Python code string to execute
 * @return 0 on success, -1 on error
 */
public static native int PyRun_SimpleString(String command);

/**
 * Execute Python source with error checking
 * @param command - Python code string to execute
 * @return 0 on success, -1 on error (with exception set)
 */
public static native int PyRun_SimpleStringFlags(String command, PyCompilerFlags flags);

/**
 * Execute Python source code in specified namespace
 * @param str - Python code string
 * @param start - Start symbol (Py_eval_input, Py_single_input, or Py_file_input)
 * @param globals - Global namespace dictionary
 * @param locals - Local namespace dictionary  
 * @return Result object, or NULL on error
 */
public static native PyObject PyRun_String(String str, int start, PyObject globals, PyObject locals);

/**
 * Execute Python source code with compiler flags
 * @param str - Python code string
 * @param start - Start symbol
 * @param globals - Global namespace dictionary
 * @param locals - Local namespace dictionary
 * @param flags - Compiler flags
 * @return Result object, or NULL on error
 */
public static native PyObject PyRun_StringFlags(String str, int start, PyObject globals, 
                                               PyObject locals, PyCompilerFlags flags);

/**
 * Execute Python file from FILE pointer
 * @param file - Open FILE pointer to Python source
 * @param filename - Filename for error reporting
 * @param start - Start symbol
 * @param globals - Global namespace dictionary
 * @param locals - Local namespace dictionary
 * @return Result object, or NULL on error
 */
public static native PyObject PyRun_File(Pointer file, String filename, int start, 
                                        PyObject globals, PyObject locals);

/**
 * Compile Python source code to code object
 * @param str - Python source code string
 * @param filename - Filename for error reporting
 * @param start - Start symbol (Py_eval_input, Py_single_input, or Py_file_input)
 * @return Compiled code object, or NULL on error
 */
public static native PyObject Py_CompileString(String str, String filename, int start);

/**
 * Compile Python source with compiler flags
 * @param str - Python source code string
 * @param filename - Filename for error reporting  
 * @param start - Start symbol
 * @param flags - Compiler flags
 * @return Compiled code object, or NULL on error
 */
public static native PyObject Py_CompileStringFlags(String str, String filename, int start, 
                                                   PyCompilerFlags flags);

/**
 * Evaluate compiled code object
 * @param code - Compiled code object
 * @param globals - Global namespace dictionary
 * @param locals - Local namespace dictionary
 * @return Result object, or NULL on error
 */
public static native PyObject PyEval_EvalCode(PyObject code, PyObject globals, PyObject locals);

/**
 * Evaluate code object with additional parameters
 * @param code - Compiled code object
 * @param globals - Global namespace dictionary
 * @param locals - Local namespace dictionary
 * @param args - Positional arguments array
 * @param argcount - Number of positional arguments
 * @param kwds - Keyword arguments array
 * @param kwdcount - Number of keyword arguments
 * @param defs - Default argument values
 * @param defcount - Number of default values
 * @param closure - Closure tuple for nested functions
 * @return Result object, or NULL on error
 */
public static native PyObject PyEval_EvalCodeEx(PyObject code, PyObject globals, PyObject locals,
                                               PointerPointer args, int argcount,
                                               PointerPointer kwds, int kwdcount,
                                               PointerPointer defs, int defcount,
                                               PyObject closure);

Execution Start Symbols:

// Execution mode constants
public static final int Py_single_input = 256;    // Single interactive statement
public static final int Py_file_input = 257;      // Complete Python file
public static final int Py_eval_input = 258;      // Single expression for evaluation

Usage Examples:

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

// Simple code execution
PyRun_SimpleString("print('Hello from Python!')");
PyRun_SimpleString("x = 42; print(f'The answer is {x}')");

// Execute code with result capture
PyObject globals = PyDict_New();
PyObject locals = PyDict_New();

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

// Evaluate expression
PyObject result = PyRun_String("x + y", Py_eval_input, globals, locals);
long sum = PyLong_AsLong(result); // 30

// Compile and execute separately
PyObject code = Py_CompileString("result = x * y", "calculation", Py_file_input);
if (code != null) {
    PyEval_EvalCode(code, globals, locals);
    
    // Get result from locals
    PyObject pyResult = PyDict_GetItemString(locals, "result");
    long product = PyLong_AsLong(pyResult); // 200
}

// Execute Python file content
String pythonScript = """
    def fibonacci(n):
        if n <= 1:
            return n
        return fibonacci(n-1) + fibonacci(n-2)
    
    result = fibonacci(10)
    """;

PyRun_String(pythonScript, Py_file_input, globals, locals);
PyObject fibResult = PyDict_GetItemString(locals, "result");
System.out.println("Fibonacci(10) = " + PyLong_AsLong(fibResult)); // 55

Callable Objects and Functions

Functions for working with callable Python objects and function calls.

/**
 * Check if object is callable
 * @param obj - Object to check
 * @return 1 if callable, 0 otherwise
 */
public static native int PyCallable_Check(PyObject obj);

/**
 * Call callable object with arguments and keywords
 * @param callable - Callable object
 * @param args - Tuple of positional arguments
 * @param kwargs - Dictionary of keyword arguments (or NULL)
 * @return Result of call, or NULL on error
 */
public static native PyObject PyObject_Call(PyObject callable, PyObject args, PyObject kwargs);

/**
 * Call callable object with tuple of arguments
 * @param callable - Callable object
 * @param args - Tuple of arguments (or NULL for no args)
 * @return Result of call, or NULL on error
 */
public static native PyObject PyObject_CallObject(PyObject callable, PyObject args);

/**
 * Call callable with formatted arguments
 * @param callable - Callable object
 * @param format - Argument format string
 * @param args - Arguments matching format
 * @return Result of call, or NULL on error
 */
public static native PyObject PyObject_CallFunction(PyObject callable, String format, Object... args);

/**
 * Call method on object with formatted arguments
 * @param obj - Object to call method on
 * @param method - Method name
 * @param format - Argument format string
 * @param args - Arguments matching format
 * @return Result of call, or NULL on error
 */
public static native PyObject PyObject_CallMethod(PyObject obj, String method, String format, Object... args);

Vectorcall Protocol (Fast Calling)

High-performance calling protocol introduced in Python 3.8+.

/**
 * Call using vectorcall protocol
 * @param callable - Callable object
 * @param args - Array of argument objects
 * @param nargsf - Number of arguments (with flags)
 * @param kwnames - Tuple of keyword names (or NULL)
 * @return Result of call, or NULL on error
 */
public static native PyObject PyObject_Vectorcall(PyObject callable, PointerPointer args, 
                                                long nargsf, PyObject kwnames);

/**
 * Call using vectorcall with dictionary keywords
 * @param callable - Callable object  
 * @param args - Array of argument objects
 * @param nargsf - Number of arguments (with flags)
 * @param kwargs - Dictionary of keyword arguments
 * @return Result of call, or NULL on error
 */
public static native PyObject PyObject_VectorcallDict(PyObject callable, PointerPointer args,
                                                    long nargsf, PyObject kwargs);

/**
 * Check if object supports vectorcall
 * @param callable - Object to check
 * @return 1 if supports vectorcall, 0 otherwise
 */
public static native int PyVectorcall_NARGS(long nargsf);

Usage Example:

// Call a Python function
PyObject func = PyObject_GetAttrString(module, "my_function");

if (PyCallable_Check(func) != 0) {
    // Create arguments tuple
    PyObject args = PyTuple_New(2);
    PyTuple_SetItem(args, 0, PyLong_FromLong(10));
    PyTuple_SetItem(args, 1, PyUnicode_FromString("test"));
    
    // Call function
    PyObject result = PyObject_CallObject(func, args);
    
    if (result != null) {
        // Process result
        System.out.println("Function returned: " + result);
    } else {
        PyErr_Clear();
    }
}

// Call method on object
PyObject obj = getMyObject();
PyObject methodResult = PyObject_CallMethod(obj, "process", "si", "data", 42);

Threading and GIL Management

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

/**
 * Get thread state for current thread
 * @return Thread state for this thread, or NULL if no Python thread state
 */
public static native PyThreadState PyGILState_GetThisThreadState();

/**
 * Check if current thread holds the GIL
 * @return 1 if GIL is held, 0 otherwise
 */
public static native int PyGILState_Check();

/**
 * Ensure current thread has the GIL
 * @return GIL state token (must be passed to PyGILState_Release)
 */
public static native @Cast("PyGILState_STATE") int PyGILState_Ensure();

/**
 * Release GIL acquired with PyGILState_Ensure
 * @param state - State token from PyGILState_Ensure
 */
public static native void PyGILState_Release(@Cast("PyGILState_STATE") int state);

/**
 * Create new thread state for interpreter
 * @param interp - Interpreter state
 * @return New thread state
 */
public static native PyThreadState PyThreadState_New(PyInterpreterState interp);

/**
 * Clear thread state (prepare for deletion)
 * @param tstate - Thread state to clear
 */
public static native void PyThreadState_Clear(PyThreadState tstate);

/**
 * Delete thread state
 * @param tstate - Thread state to delete
 */
public static native void PyThreadState_Delete(PyThreadState tstate);

/**
 * Get current thread state
 * @return Current thread state
 */
public static native PyThreadState PyThreadState_Get();

/**
 * Swap thread state (make different thread state current)
 * @param tstate - New thread state (or NULL)
 * @return Previous thread state
 */
public static native PyThreadState PyThreadState_Swap(PyThreadState tstate);

Usage Example:

// Proper GIL management from Java thread
public class PythonWorker {
    
    public void doWorkInPython() {
        // Acquire GIL
        int gilState = PyGILState_Ensure();
        
        try {
            // Now safe to call Python API
            PyObject result = PyRun_SimpleString("print('Hello from Java thread')");
            
            // More Python operations...
            
        } finally {
            // Always release GIL
            PyGILState_Release(gilState);
        }
    }
    
    public void longRunningTask() {
        int gilState = PyGILState_Ensure();
        
        try {
            // Do some Python setup
            PyObject data = PyList_New(1000000);
            
            // Release GIL for long computation
            PyGILState_Release(gilState);
            gilState = null;
            
            // Do Java computation without holding GIL
            doExpensiveJavaComputation();
            
            // Re-acquire GIL for Python work
            gilState = PyGILState_Ensure();
            
            // Continue with Python operations
            PyList_Append(data, PyUnicode_FromString("done"));
            
        } finally {
            if (gilState != 0) {
                PyGILState_Release(gilState);
            }
        }
    }
    
    private void doExpensiveJavaComputation() {
        // Long-running Java code that doesn't need Python
        // Good to release GIL during this
    }
}

Type System Operations

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

/**
 * Prepare type object for use (must be called before using custom types)
 * @param type - Type object to prepare
 * @return 0 on success, -1 on error
 */
public static native int PyType_Ready(PyTypeObject type);

/**
 * Create type from specification
 * @param spec - Type specification structure
 * @return New type object, or NULL on error
 */
public static native PyTypeObject PyType_FromSpec(PyType_Spec spec);

/**
 * Create type from specification with base classes
 * @param spec - Type specification
 * @param bases - Tuple of base classes
 * @return New type object, or NULL on error
 */
public static native PyTypeObject PyType_FromSpecWithBases(PyType_Spec spec, PyObject bases);

/**
 * Create type from specification with module association
 * @param module - Module to associate type with
 * @param spec - Type specification
 * @param bases - Tuple of base classes
 * @return New type object, or NULL on error
 */
public static native PyTypeObject PyType_FromModuleAndSpec(PyObject module, PyType_Spec spec, PyObject bases);

/**
 * Check if one type is subtype of another
 * @param a - Potential subtype
 * @param b - Potential base type
 * @return 1 if a is subtype of b, 0 otherwise
 */
public static native int PyType_IsSubtype(PyTypeObject a, PyTypeObject b);

/**
 * Check if object is instance of class
 * @param obj - Object to check
 * @param cls - Class to check against
 * @return 1 if instance, 0 if not, -1 on error
 */
public static native int PyObject_IsInstance(PyObject obj, PyObject cls);

/**
 * Check if one class is subclass of another
 * @param derived - Potential subclass
 * @param cls - Potential base class  
 * @return 1 if subclass, 0 if not, -1 on error
 */
public static native int PyObject_IsSubclass(PyObject derived, PyObject cls);

Type Data Management

/**
 * Get size of type-specific data
 * @param cls - Type object
 * @return Size of type data in bytes
 */
public static native long PyType_GetTypeDataSize(PyTypeObject cls);

/**
 * Get pointer to type-specific data
 * @param cls - Type object  
 * @param base - Base type that defines the data
 * @return Pointer to type data
 */
public static native Pointer PyType_GetTypeData(PyTypeObject cls, PyTypeObject base);

Usage Example:

// Check types and inheritance
PyObject obj = getMyObject();
PyObject listType = PyList_Type(); // Assuming this exists

// Check if object is a list
if (PyObject_IsInstance(obj, listType) == 1) {
    System.out.println("Object is a list");
}

// Check type inheritance
PyTypeObject customType = getCustomType();
if (PyType_IsSubtype(customType, listType) == 1) {
    System.out.println("Custom type inherits from list");
}

Mathematical and Utility Constants

Important constants for mathematical operations and system limits.

/**
 * Mathematical constants
 */
public static final double Py_MATH_PI = 3.14159265358979323846;
public static final double Py_MATH_E = 2.7182818284590452354;
public static final double Py_MATH_TAU = 6.2831853071795864769252867665590057683943;

/**
 * Get positive infinity value
 * @return Positive infinity as double
 */
public static native double Py_INFINITY();

/**
 * Build and version constants
 */
public static final int Py_ENABLE_SHARED = 1;
public static final int Py_CAN_START_THREADS = 1;

Advanced Object Operations

Additional object manipulation and introspection functions.

/**
 * Get object's string representation
 * @param obj - Object to get representation of
 * @return String representation, or NULL on error
 */
public static native PyObject PyObject_Str(PyObject obj);

/**
 * Get object's printable representation  
 * @param obj - Object to get representation of
 * @return Printable representation, or NULL on error
 */
public static native PyObject PyObject_Repr(PyObject obj);

/**
 * Get object's ASCII representation
 * @param obj - Object to get representation of
 * @return ASCII representation, or NULL on error
 */
public static native PyObject PyObject_ASCII(PyObject obj);

/**
 * Get object's bytes representation
 * @param obj - Object to convert to bytes
 * @return Bytes object, or NULL on error
 */
public static native PyObject PyObject_Bytes(PyObject obj);

/**
 * Check if object is true in boolean context
 * @param obj - Object to check
 * @return 1 if true, 0 if false, -1 on error
 */
public static native int PyObject_IsTrue(PyObject obj);

/**
 * Check if object is false in boolean context  
 * @param obj - Object to check
 * @return 1 if false, 0 if true, -1 on error
 */
public static native int PyObject_IsFalse(PyObject obj);

/**
 * Get length of object
 * @param obj - Object to get length of
 * @return Length, or -1 on error
 */
public static native long PyObject_Length(PyObject obj);

Key Utility Types

/**
 * Buffer view structure for buffer protocol
 */
class Py_buffer extends Pointer {
    // Contains:
    // - buf: pointer to buffer data
    // - len: length in bytes  
    // - readonly: read-only flag
    // - format: format string
    // - ndim: number of dimensions
    // - shape: array of dimension sizes
    // - strides: array of strides
    // - suboffsets: suboffsets array
}

/**
 * Type specification for creating new types
 */
class PyType_Spec extends Pointer {
    // Contains:
    // - name: type name
    // - basicsize: basic instance size
    // - itemsize: variable part size
    // - flags: type flags
    // - slots: array of slot definitions
}

/**
 * GIL state enumeration (returned as int)
 */
public static final int PyGILState_STATE = 0; // Enum value cast to int

/**
 * Thread state object
 */
class PyThreadState extends Pointer { }

/**
 * Interpreter state object
 */
class PyInterpreterState extends Pointer { }

Advanced Usage Patterns

High-Performance Buffer Operations

public class BufferOperations {
    
    public static void processLargeArray(PyObject arrayObj) {
        Py_buffer buffer = new Py_buffer();
        
        if (PyObject_GetBuffer(arrayObj, buffer, PyBUF_C_CONTIGUOUS) == 0) {
            try {
                long itemCount = buffer.len() / buffer.itemsize();
                
                // Check if contiguous for fast access
                if (PyBuffer_IsContiguous(buffer, 'C') == 1) {
                    // Direct memory access for maximum performance
                    Pointer data = buffer.buf();
                    
                    // Process data directly in native code
                    processNativeBuffer(data, itemCount);
                } else {
                    // Copy to contiguous buffer first
                    Pointer contiguous = PyMem_Malloc(buffer.len());
                    PyBuffer_ToContiguous(contiguous, buffer, buffer.len(), 'C');
                    
                    processNativeBuffer(contiguous, itemCount);
                    
                    // Copy back if buffer is writable
                    if (buffer.readonly() == 0) {
                        PyBuffer_FromContiguous(buffer, contiguous, buffer.len(), 'C');
                    }
                    
                    PyMem_Free(contiguous);
                }
                
            } finally {
                PyBuffer_Release(buffer);
            }
        }
    }
    
    private static native void processNativeBuffer(Pointer data, long count);
}

Thread Pool Integration

public class PythonThreadPool {
    
    private final ExecutorService executor;
    
    public PythonThreadPool(int threadCount) {
        this.executor = Executors.newFixedThreadPool(threadCount);
    }
    
    public CompletableFuture<PyObject> submitPythonTask(String pythonCode) {
        return CompletableFuture.supplyAsync(() -> {
            int gilState = PyGILState_Ensure();
            
            try {
                return PyRun_SimpleString(pythonCode);
            } finally {
                PyGILState_Release(gilState);
            }
        }, executor);
    }
    
    public void shutdown() {
        executor.shutdown();
    }
}

Custom Type Creation

public class CustomTypeBuilder {
    
    public static PyTypeObject createCustomListType() {
        // This is a simplified example - real type creation
        // requires more detailed slot filling
        
        PyType_Spec spec = new PyType_Spec();
        // Fill spec with type information
        // spec.name = "CustomList"
        // spec.basicsize = sizeof(CustomListObject)
        // spec.flags = Py_TPFLAGS_DEFAULT
        
        PyTypeObject newType = PyType_FromSpec(spec);
        
        if (newType != null) {
            // Prepare the type for use
            if (PyType_Ready(newType) < 0) {
                return null;
            }
        }
        
        return newType;
    }
}

Performance Optimization Tips

Efficient Function Calling

// Use vectorcall for better performance when available
if (supportsVectorcall(func)) {
    PointerPointer args = new PointerPointer(argArray);
    PyObject result = PyObject_Vectorcall(func, args, argCount, null);
} else {
    // Fall back to traditional calling
    PyObject argTuple = createArgTuple(argArray);
    PyObject result = PyObject_CallObject(func, argTuple);
}

Buffer Protocol Optimization

// Request specific buffer format for optimal performance
int flags = PyBUF_C_CONTIGUOUS | PyBUF_FORMAT;
if (PyObject_GetBuffer(obj, buffer, flags) == 0) {
    // Got optimal buffer format
} else {
    // Fall back to simple buffer
    PyErr_Clear();
    PyObject_GetBuffer(obj, buffer, PyBUF_SIMPLE);
}

GIL Management Best Practices

// Minimize GIL hold time
int gilState = PyGILState_Ensure();
PyObject data = extractPythonData(); // Quick Python operation
PyGILState_Release(gilState);

// Do heavy computation without GIL
Object processedData = processInJava(data);

// Re-acquire GIL for final Python operations
gilState = PyGILState_Ensure();
storePythonResult(processedData);
PyGILState_Release(gilState);

Important Notes

Thread Safety

  • Always use GIL management when calling from multiple Java threads
  • Buffer protocol operations are not thread-safe without proper locking
  • Type creation should be done during initialization, not from multiple threads

Memory Management

  • Always release buffers with PyBuffer_Release()
  • GIL state tokens must be properly matched with PyGILState_Release()
  • Custom types require careful reference counting

Performance Considerations

  • Vectorcall protocol provides significant performance benefits for frequent function calls
  • Contiguous buffers allow for maximum performance in data processing
  • Minimize GIL acquire/release cycles for better concurrency

Error Handling

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

Install with Tessl CLI

npx tessl i tessl/maven-org-bytedeco--cpython

docs

exceptions.md

index.md

initialization.md

memory-management.md

modules.md

objects.md

utilities.md

tile.json