### Configure Setuptools for CFFI Source: https://github.com/python-cffi/cffi/blob/main/doc/source/overview.md Example setup.py configuration for distributing CFFI modules. ```python from setuptools import setup setup( ... setup_requires=["cffi>=1.0.0"], cffi_modules=["simple_example_build.py:ffibuilder"], install_requires=["cffi>=1.0.0"], ) ``` -------------------------------- ### Install CFFI via pip Source: https://github.com/python-cffi/cffi/blob/main/doc/source/installation.md Standard installation command for CPython environments. ```bash pip install cffi ``` -------------------------------- ### Install pytest and CFFI for Development Source: https://github.com/python-cffi/cffi/blob/main/README.md Install pytest for testing and CFFI in editable mode for local development. Run tests using pytest. ```bash pip install pytest pip install -e . # editable install of CFFI for local development pytest src/c/ testing/ ``` -------------------------------- ### Define C source and header files Source: https://github.com/python-cffi/cffi/blob/main/doc/source/overview.md Example C implementation and header for a custom library. ```c /* filename: pi.c*/ # include # include /* Returns a very crude approximation of Pi given an int: a number of iterations */ float pi_approx(int n){ double i,x,y,sum=0; for(i=0;i=1.0.0"], cffi_modules=["example_build.py:ffibuilder"], install_requires=["cffi>=1.0.0"], ) ``` -------------------------------- ### Configure setup.py for version compatibility Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md Conditional setup configuration to handle differences between CFFI 0.9 and 1.0. ```python if requires_cffi.startswith("cffi==0."): # backward compatibility: we have "cffi==0.*" from package.foo_build import ffi extra_args = dict( ext_modules=[ffi.verifier.get_extension()], ext_package="...", # if needed ) else: extra_args = dict( setup_requires=[requires_cffi], cffi_modules=['package/foo_build.py:ffi'], ) setup( name=..., ..., install_requires=[requires_cffi], **extra_args ) ``` -------------------------------- ### Install CFFI on macOS with Homebrew Source: https://github.com/python-cffi/cffi/blob/main/doc/source/installation.md Commands to install dependencies and CFFI on macOS using Homebrew. ```bash brew install pkg-config libffi PKG_CONFIG_PATH=$(brew --prefix libffi)/lib/pkgconfig pip install --no-binary cffi cffi ``` -------------------------------- ### Integrate CFFI with Setuptools Source: https://github.com/python-cffi/cffi/blob/main/doc/source/overview.md Configures a project to build CFFI modules automatically during installation using the setup.py file. ```python from setuptools import setup setup( ... setup_requires=["cffi>=1.0.0"], cffi_modules=["piapprox_build:ffibuilder"], # "filename:global" install_requires=["cffi>=1.0.0"], ) ``` -------------------------------- ### Initialize C99 Variable-Sized Structures Source: https://github.com/python-cffi/cffi/blob/main/doc/source/using.md Examples of initializing structures containing flexible array members. ```python p = ffi.new("foo_t *", [5, [6, 7, 8]]) # length 3 p = ffi.new("foo_t *", [5, 3]) # length 3 with 0 in the array p = ffi.new("foo_t *", {'y': 3}) # length 3 with 0 everywhere ``` -------------------------------- ### Configure CFFI Build Script for Callbacks Source: https://github.com/python-cffi/cffi/blob/main/doc/source/using.md Setup for CFFI build script using extern Python callbacks. ```python ffibuilder.cdef(""" typedef ... event_t; typedef void (*event_cb_t)(event_t *evt, void *userdata); void event_cb_register(event_cb_t cb, void *userdata); extern "Python" void my_event_callback(event_t *, void *); """) ffibuilder.set_source("_demo_cffi", r""" #include """) ``` -------------------------------- ### Build and install CFFI in a virtual environment Source: https://github.com/python-cffi/cffi/blob/main/doc/source/installation.md Manual build process to ensure compatibility with the target Python interpreter. ```bash virtualenv ~/venv cd ~/path/to/sources/of/cffi ~/venv/bin/python setup.py build --force ~/venv/bin/python setup.py install ``` -------------------------------- ### CFFI In-line ABI Mode Example Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md Use this mode for simple, direct access to C libraries without complex build steps. It requires importing cffi and using ffi.cdef() and ffi.dlopen(). ```python import cffi ffi = cffi.FFI() ffi.cdef("C-like declarations") lib = ffi.dlopen("libpath") # use ffi and lib here ``` -------------------------------- ### Initialize CFFI Library Interface Source: https://github.com/python-cffi/cffi/blob/main/doc/source/using.md Setup the FFI object and define the C function signature to be loaded from a shared library. ```python from cffi import FFI ffi = FFI() ffi.cdef(""" int main_like(int argv, char *argv[]); """) lib = ffi.dlopen("some_library.so") ``` -------------------------------- ### Determine CFFI version for setup.py Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md Logic to detect the installed CFFI version, accounting for PyPy built-in modules. ```python if '_cffi_backend' in sys.builtin_module_names: # PyPy import _cffi_backend requires_cffi = "cffi==" + _cffi_backend.__version__ else: requires_cffi = "cffi>=1.0.0" ``` -------------------------------- ### Copy memory with ffi.memmove Source: https://github.com/python-cffi/cffi/blob/main/doc/source/ref.md Examples of copying data between pointers and buffer-supporting objects. ```python ffi.memmove(myptr, b"hello", 5) ``` ```python ba = bytearray(100); ffi.memmove(ba, myptr, 100) ``` ```python ffi.memmove(myptr + 1, myptr, 100) ``` -------------------------------- ### Run CFFI tests Source: https://github.com/python-cffi/cffi/blob/main/doc/source/installation.md Execute the test suite using pytest. Requires a prior build if not installed. ```bash pytest c/ testing/ ``` ```bash python setup_base.py build_ext -f -i ``` -------------------------------- ### Demonstrate Race Conditions in Threaded CFFI Source: https://github.com/python-cffi/cffi/blob/main/doc/source/overview.md Example script showing how concurrent access to a C library without synchronization can lead to race conditions. ```python # free-threaded build. sys.setswitchinterval(.0000001) N_WORKERS = 4 l = threading.Lock() def work(): lib.increment() def run_thread_pool(): with ThreadPoolExecutor(max_workers=N_WORKERS) as tpe: try: futures = [tpe.submit(work) for _ in range(100000)] # block until all work finishes wait(futures) finally: # check for exceptions in worker threads [f.result() for f in futures] run_thread_pool() print(lib.increment()) ``` -------------------------------- ### Define C Callback Types Source: https://github.com/python-cffi/cffi/blob/main/doc/source/using.md Example C type definitions for event callbacks. ```c typedef void (*event_cb_t)(event_t *evt, void *userdata); ``` ```c void event_cb_register(event_cb_t cb, void *userdata); ``` -------------------------------- ### Call C Functions with Integer Arguments Source: https://github.com/python-cffi/cffi/blob/main/doc/source/using.md Basic function call example showing integer passing and overflow behavior. ```python # int foo(short a, int b); n = lib.foo(2, 3) # returns a normal integer lib.foo(40000, 3) # raises OverflowError ``` -------------------------------- ### Use relative_to in ffi.verify() Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md The relative_to argument ensures that local source files are correctly located even after the project is installed. ```default ext = ffi.verify(..., sources=['foo.c'], relative_to=__file__) ``` ```default ext = ffi.verify(..., sources=['/path/to/this/file/foo.c']) ``` -------------------------------- ### ffi.cdef() - Preprocessing Directives and Macros Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md Explains how ffi.cdef() handles C preprocessor directives and provides an example of removing SAL annotations using `re.sub` for cleaner C declarations. ```APIDOC ## ffi.cdef() - Preprocessor Directives and Macros ### Description The underlying C parser (`pycparser`) used by `ffi.cdef()` recognizes preprocessor-like directives (e.g., `# NUMBER`). However, C `#include` directives are not supported within the `cdef` source string. ### Handling Macros (e.g., SAL Annotations) When copying C code that includes macros (like SAL annotations on Windows, e.g., `_In_`, `_Out_`), these must be removed before passing the string to `ffi.cdef()`. This can be done programmatically. ### Request Example ```python import cffi import re ffi = cffi.FFI() source_with_macros = """ DWORD WINAPI GetModuleFileName( _In_opt_ HMODULE hModule, _Out_ LPTSTR lpFilename, _In_ DWORD nSize ); """ # Remove SAL annotations using regex cleaned_source = re.sub(r"\b(_In_|_Inout_|_Out_|_Outptr_)(opt_)?\b", " ", source_with_macros) ffi.cdef(cleaned_source) ``` ### Note Ensure that any macros or preprocessor directives that are not standard C declarations are handled or removed appropriately before calling `ffi.cdef()` to avoid parsing errors. ``` -------------------------------- ### Setuptools function-based configuration Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md Alternative configuration for setup.py using a global function to return an FFI object. ```python cffi_modules=["path/to/foo_build.py:maker"] ``` -------------------------------- ### Get address of struct/union Source: https://github.com/python-cffi/cffi/blob/main/doc/source/ref.md Use ffi.addressof() to get a pointer to a C struct or union. The returned pointer is only valid as long as the original cdata object is alive. ```python ffi.addressof() ``` -------------------------------- ### Initialize Structs with ffi.new Source: https://github.com/python-cffi/cffi/blob/main/doc/source/using.md Shows how to initialize C structs using Python lists or dictionaries as equivalents to C syntax. ```python typedef struct { int x, y; } foo_t; foo_t v = { 1, 2 }; // C syntax v = ffi.new("foo_t *", [1, 2]) # CFFI equivalent foo_t v = { .y=1, .x=2 }; // C99 syntax v = ffi.new("foo_t *", {'y': 1, 'x': 2}) # CFFI equivalent ``` -------------------------------- ### Get address of library symbol Source: https://github.com/python-cffi/cffi/blob/main/doc/source/ref.md Use ffi.addressof() with a library object and symbol name to get the address of a function or global variable. For functions, this returns a cdata pointer. ```python ffi.addressof(lib, "name") ``` -------------------------------- ### Get offset of struct field Source: https://github.com/python-cffi/cffi/blob/main/doc/source/ref.md Use ffi.offsetof() to get the byte offset of a field within a C struct or array type. Supports nested structures and array indexing. ```python ffi.offsetof("int[5]", 2) ``` ```python ffi.offsetof("int *", 2) ``` -------------------------------- ### CFFI Setuptools Integration for setup.py Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md Recommended integration for CFFI modules with Setuptools. This supports out-of-line mode (ABI or API) and provides automatic dependency tracking. The compilation is handled by Setuptools. ```python # setup.py (with automatic dependency tracking) from setuptools import setup setup( ..., setup_requires=["cffi>=1.0.0"], cffi_modules=["package/foo_build.py:ffibuilder"], install_requires=["cffi>=1.0.0"], ) ``` -------------------------------- ### Get address of struct field or array item Source: https://github.com/python-cffi/cffi/blob/main/doc/source/ref.md Use ffi.addressof() with a cdata object and field/index to get the address of a nested member or array element. Equivalent to C's '&' operator. ```python ffi.addressof(array, index) ``` -------------------------------- ### ffibuilder.distutils_extension() Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md Creates a distutils Extension instance for setup.py files. ```APIDOC ## ffibuilder.distutils_extension(tmpdir='build', verbose=True) ### Description Creates the .c file if needed and returns a distutils.core.Extension instance for use in setup.py. ### Parameters #### Query Parameters - **tmpdir** (string) - Optional - The directory to create the .c file. Defaults to 'build'. - **verbose** (boolean) - Optional - Controls output verbosity. Defaults to True. ``` -------------------------------- ### Setuptools configuration Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md Configuration line for setup.py to integrate CFFI modules with Setuptools. ```python cffi_modules=["path/to/foo_build.py:ffibuilder"] ``` -------------------------------- ### C Const Variable Declaration Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md Example of declaring a constant character pointer in C syntax. ```c static char *const FOO; ``` -------------------------------- ### Initialize Character Arrays Source: https://github.com/python-cffi/cffi/blob/main/doc/source/using.md Illustrates initializing char arrays from strings and accessing array elements. ```python >>> x = ffi.new("char[]", "hello") >>> x >>> len(x) # the actual size of the array 6 >>> x[5] # the last item in the array '\x00' >>> x[0] = 'H' # change the first item >>> ffi.string(x) # interpret 'x' as a regular null-terminated string 'Hello' ``` -------------------------------- ### Initialize API mode in CFFI Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md Standard initialization for projects using ffi.verify(). ```python import cffi ffi = cffi.FFI() ffi.cdef("stuff") lib = ffi.verify("real C code") ``` -------------------------------- ### Configure include paths for libffi on macOS Source: https://github.com/python-cffi/cffi/blob/main/doc/source/installation.md Modify setup.py include directories for manual libffi builds on older macOS versions. ```python include_dirs = [] ``` ```python include_dirs = ['/usr/local/lib/libffi-3.0.11/include'] ``` -------------------------------- ### ffibuilder.set_source_pkgconfig() Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md Equivalent to set_source but automatically retrieves library information using the system pkg-config utility. ```APIDOC ## ffibuilder.set_source_pkgconfig(module_name, pkgconfig_libs, c_header_source, **keywords) ### Description Calls the system utility 'pkg-config' to collect library information and adds it to the provided keywords. Useful for linking against system-installed libraries. ### Parameters - **module_name** (string) - Required - The name of the Python module to generate. - **pkgconfig_libs** (list) - Required - A list of package names to query via pkg-config. - **c_header_source** (string) - Required - C code string to be included in the generated .c file. - **keywords** (dict) - Optional - Additional compiler arguments. ``` -------------------------------- ### Initialize ABI mode in CFFI Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md Standard initialization for projects using ffi.dlopen(). ```python import cffi ffi = cffi.FFI() ffi.cdef("stuff") lib = ffi.dlopen("libpath") ``` -------------------------------- ### Detect infinite recursion in struct definitions Source: https://github.com/python-cffi/cffi/blob/main/doc/source/whatsnew.md Example of a struct definition that triggers an infinite recursion detection in CFFI. ```python ffi.cdef("""struct X { void(*fnptr)(struct X); };""") ``` -------------------------------- ### Initialize Arrays by Length Source: https://github.com/python-cffi/cffi/blob/main/doc/source/using.md Shows how to initialize arrays by specifying length for zero-initialization. ```python int array[1000]; // C syntax array = ffi.new("int[1000]") # CFFI 1st equivalent array = ffi.new("int[]", 1000) # CFFI 2nd equivalent ``` -------------------------------- ### Manual Memory Management with malloc/free Source: https://github.com/python-cffi/cffi/blob/main/doc/source/ref.md Demonstrates how to use C's malloc and free functions directly through CFFI for explicit memory control. ```APIDOC ## Manual Memory Management with malloc/free ### Description This section shows how to use the C standard library's `malloc` and `free` functions to manage memory manually within CFFI. This provides precise control over when memory is allocated and deallocated, which can be crucial for avoiding memory leaks or managing large allocations. ### Method Declare and call C functions `malloc` and `free`. ### Endpoint N/A (Internal CFFI usage) ### Parameters N/A ### Request Example ```python from cffi import FFI ffi = FFI() lib = ffi.dlopen(None) # Load the C standard library ffi.cdef("void *malloc(size_t size); void free(void *ptr);") n = 10 p = lib.malloc(n * ffi.sizeof("int")) try: my_array = ffi.cast("int *", p) # Use my_array here for i in range(n): my_array[i] = i print(my_array[:n]) finally: lib.free(p) ``` ### Response N/A (This is a code example for memory management, not an API endpoint response.) ``` -------------------------------- ### Create a backward-compatible build script Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md A build script that supports both CFFI 0.9 and 1.0 by checking for set_source. ```python # in a separate file "package/foo_build.py" import cffi ffi = cffi.FFI() C_HEADER_SRC = r''' #include "somelib.h" ''' C_KEYWORDS = dict(libraries=['somelib']) if hasattr(ffi, 'set_source'): ffi.set_source("package._foo", C_HEADER_SRC, **C_KEYWORDS) ffi.cdef(''' int foo(int); ''') if __name__ == "__main__": ffi.compile() ``` -------------------------------- ### Cast Types with ffi.cast Source: https://github.com/python-cffi/cffi/blob/main/doc/source/using.md Provides examples of casting values to specific C types and converting pointers to integer types. ```python >>> x = ffi.cast("int", 42) >>> x >>> int(x) 42 ``` ```python >>> int(ffi.cast("intptr_t", pointer_cdata)) # signed -1340782304 >>> int(ffi.cast("uintptr_t", pointer_cdata)) # unsigned 2954184992L ``` -------------------------------- ### Allocate and Use C Pointers Source: https://github.com/python-cffi/cffi/blob/main/doc/source/using.md Demonstrates allocating a single integer pointer, assigning a value, and passing it to a C function. ```python x = ffi.new("int *") # allocate one int, and return a pointer to it x[0] = 42 # fill it lib.somefunction(x) # call the C function print x[0] # read the possibly-changed value ``` -------------------------------- ### Compile with RPATH and Shell Escaping Source: https://github.com/python-cffi/cffi/blob/main/doc/source/embedding.md Examples of using GCC flags to set RPATH, including necessary shell escaping for $ORIGIN. ```bash gcc -Wl,-rpath=/some/path ``` ```bash gcc -Wl,-rpath=\$ORIGIN ``` ```bash gcc -Wl,-rpath=\$$ORIGIN ``` -------------------------------- ### ffi.new() - Creating C Data Types Source: https://github.com/python-cffi/cffi/blob/main/doc/source/using.md Demonstrates the use of `ffi.new()` to allocate and initialize C data types such as pointers, arrays, and C strings. It highlights the difference between allocating a single character pointer and a null-terminated C string. ```APIDOC ## POST /ffi.new ### Description Allocates and returns a new cdata object of the given C type. The memory is initially filled with zeros, and an optional initializer can be provided. ### Method POST ### Endpoint /ffi.new ### Parameters #### Request Body - **ctype** (string) - Required - A string describing the C type (e.g., "int *", "int[10]", "char[]"). - **initializer** (any) - Optional - A value or sequence to initialize the allocated memory. ### Request Example ```json { "ctype": "int *" } ``` ```json { "ctype": "int[10]" } ``` ```json { "ctype": "char[]", "initializer": "foobar" } ``` ### Response #### Success Response (200) - **cdata_object** (object) - A cdata object representing the allocated C data type. #### Response Example ```json { "cdata_object": "" } ``` ```json { "cdata_object": "" } ``` ```json { "cdata_object": "" } ``` ``` -------------------------------- ### Call Python from Custom C Logic Source: https://github.com/python-cffi/cffi/blob/main/doc/source/using.md Example of calling a Python function from within custom C code using a forward declaration. ```c ffibuilder.cdef(""" extern "Python" int f(int); int my_algo(int); """) ffibuilder.set_source("_example_cffi", r""" static int f(int); /* the forward declaration */ static int my_algo(int n) { int i, sum = 0; for (i = 0; i < n; i++) sum += f(i); /* call f() here */ return sum; } """) ``` -------------------------------- ### CFFI Distutils Integration for setup.py Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md Integrate CFFI modules into a Distutils setup.py file for building C extensions. This method is for out-of-line API mode and is deprecated since Python 3.10. ```python # setup.py (requires CFFI to be installed first) from distutils.core import setup import foo_build # possibly with sys.path tricks to find it setup( ..., ext_modules=[foo_build.ffibuilder.distutils_extension()], ) ``` -------------------------------- ### ffi.dlopen() Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md Loads a shared library and returns a library object for ABI-level access to C functions and variables. ```APIDOC ## ffi.dlopen(libpath, [flags]) ### Description Opens a shared library and returns a module-like library object. This provides ABI-level access to the system, allowing calls to functions previously declared by ffi.cdef(). ### Parameters #### Path Parameters - **libpath** (string or None) - Required - The file name of the shared library. If None, returns the standard C library (not supported on Windows). #### Query Parameters - **flags** (int) - Optional - Flags passed to dlopen (ignored on Windows). Defaults to ffi.RTLD_NOW. ### Response - **library object** (object) - A library object that provides access to functions and global variables declared in the ffi instance. ``` -------------------------------- ### Slicing cdata arrays Source: https://github.com/python-cffi/cffi/blob/main/doc/source/ref.md Slicing cdata arrays requires explicit `start` and `stop` indices. It returns a cdata 'view'. Slice assignment requires matching lengths and accepts iterables. ```python ffi.cdef("int arr[10];"); c_array = ffi.new("int[10]") # Get a view of elements from index 2 up to (but not including) 5 sub_array = c_array[2:5] # Assign to a slice (length must match) new_values = [10, 20, 30] c_array[2:5] = new_values # Example with char array and string assignment (exact length required) char_arr = ffi.new("char[10]") char_arr[1:6] = b"hello" # Assigns 'h','e','l','l','o' to indices 1-5 ``` -------------------------------- ### Call C functions with ABI mode Source: https://github.com/python-cffi/cffi/blob/main/doc/source/overview.md Demonstrates loading the C namespace and calling printf using FFI. Note that char* arguments require bytes objects. ```python >>> from cffi import FFI >>> ffi = FFI() >>> ffi.cdef(""" ... int printf(const char *format, ...); // copy-pasted from the man page ... """) >>> C = ffi.dlopen(None) # loads the entire C namespace >>> arg = ffi.new("char[]", b"world") # equivalent to C code: char arg[] = "world"; >>> C.printf(b"hi there, %s.\n", arg) # call printf hi there, world. 17 # this is the return value >>> ``` -------------------------------- ### ffibuilder.compile() Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md Explicitly generates the .py or .c file and compiles it if necessary. ```APIDOC ## ffibuilder.compile(tmpdir='.', verbose=False, debug=None) ### Description Explicitly generates the .py or .c file, and compiles it if it is a .c file. The output is placed in the specified directory. ### Parameters #### Query Parameters - **tmpdir** (string) - Optional - The directory where output files are placed. Defaults to '.' - **verbose** (boolean) - Optional - If True, prints distutils output and compiler command lines. - **debug** (boolean) - Optional - Controls whether the C code is compiled in debug mode. Defaults to host Python's sys.flags.debug. ``` -------------------------------- ### Get C Type String Representation with ffi.getctype() Source: https://github.com/python-cffi/cffi/blob/main/doc/source/ref.md Use ffi.getctype() to obtain the string representation of a C type. An optional 'extra' string can be appended or inserted for declarations like pointers or arrays. ```python ffi.getctype("char[80]", "a") == "char a[80]" ``` -------------------------------- ### Get Windows Error Code with ffi.getwinerror() Source: https://github.com/python-cffi/cffi/blob/main/doc/source/ref.md On Windows, use `ffi.getwinerror()` to retrieve the `GetLastError()` value. It returns a tuple of the error code and a descriptive message. An optional code can be provided to format a specific error. ```python ffi.getwinerror(code=-1) ``` -------------------------------- ### Enable symbol versioning information Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md Set to a non-empty string to display symbol versioning information when querying the program via the dynamic linker. ```bash export LD_VERBOSE=1 ``` -------------------------------- ### ffi.dlopen() and ffi.dlclose() Source: https://github.com/python-cffi/cffi/blob/main/doc/source/ref.md Functions for loading and closing dynamic libraries. ```APIDOC ## ffi.dlopen(libpath, [flags]) ### Description Opens and returns a handle to a dynamic library as a `` object. ## ffi.dlclose(lib) ### Description Explicitly closes a `` object returned by `ffi.dlopen()`. ``` -------------------------------- ### Manage Library Paths with Environment Variables Source: https://github.com/python-cffi/cffi/blob/main/doc/source/embedding.md Commands for setting library search paths during compilation or execution. ```bash LD_LIBRARY_PATH=/some/path/to/libpypy gcc ``` ```bash LD_LIBRARY_PATH=/some/path/to/libpypy ``` ```bash DYLD_LIBRARY_PATH=/some/path/to/libpypy ``` -------------------------------- ### ffibuilder.set_source() Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md Prepares the FFI for producing an out-of-line external module. It records arguments for later use in generating C code. ```APIDOC ## ffibuilder.set_source(module_name, c_header_source, **keywords) ### Description Prepares the FFI for producing an out-of-line external module. This method does not write files immediately but records arguments for later processing. ### Parameters - **module_name** (string) - Required - The name or dotted name of the Python module to generate. - **c_header_source** (string) - Required - C code string to be included in the generated .c file. Use None for ABI mode. - **keywords** (dict) - Optional - Compiler arguments passed to distutils/setuptools (e.g., sources, include_dirs, libraries, extra_compile_args). ### Request Example ffibuilder.set_source("mymodule", r''' extern "C" { int somefunc(int somearg) { return real_cpp_func(somearg); } } ''', source_extension='.cpp') ``` -------------------------------- ### Initialize API mode build script Source: https://github.com/python-cffi/cffi/blob/main/doc/source/overview.md Initializes the FFI builder for API mode, which requires a C compiler for better performance and safety. ```python # file "example_build.py" # Note: we instantiate the same 'cffi.FFI' class as in the previous # example, but call the result 'ffibuilder' now instead of 'ffi'; ``` -------------------------------- ### Enable dynamic linker verbose debugging Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md Set this variable to output verbose information about the dynamic linker, using 'all' for full details or 'help' for configuration options. ```bash export LD_TRACE_LOADED_OBJECTS=all ``` -------------------------------- ### Handling FILE* with CFFI Source: https://github.com/python-cffi/cffi/blob/main/doc/source/ref.md Demonstrates how to interface with C FILE* objects using Python file objects. For finer control over buffering and flushing, explicit handling with fdopen() is recommended. ```python ffi.cdef (''' FILE *fdopen(int, const char *); // from the C int fclose(FILE *); ''') myfile.flush() # make sure the file is flushed newfd = os.dup(myfile.fileno()) # make a copy of the file descriptor p = lib.fdopen(newfd, "w") # make a cdata 'FILE *' around newfd lib.write_stuff_to_file(fp) # invoke the external function lib.fclose(fp) # when you're done, close fp (and newfd) ``` -------------------------------- ### Manipulate structs and arrays Source: https://github.com/python-cffi/cffi/blob/main/doc/source/overview.md Shows how to define a struct and use ffi.buffer for efficient binary I/O operations. ```python from cffi import FFI ffi = FFI() ffi.cdef(""" typedef struct { unsigned char r, g, b; } pixel_t; "") image = ffi.new("pixel_t[]", 800*600) f = open('data', 'rb') # binary mode -- important f.readinto(ffi.buffer(image)) f.close() image[100].r = 255 image[100].g = 192 image[100].b = 128 f = open('data', 'wb') f.write(ffi.buffer(image)) f.close() ``` -------------------------------- ### ffibuilder.emit_python_code() Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md Generates the specified .py file for ABI mode. ```APIDOC ## ffibuilder.emit_python_code(filename) ### Description Generates the given .py file for ABI mode. The generated code is identical across Python versions. ### Parameters #### Path Parameters - **filename** (string or file-like object) - Required - The path to the file to write or a file-like object. ``` -------------------------------- ### Callback with Context Handle Source: https://github.com/python-cffi/cffi/blob/main/doc/source/using.md Demonstrates a recommended pattern for using callbacks with context. A handle is created using ffi.new_handle() and kept alive, allowing the callback to access object methods via the handle. ```python # a good way to use this decorator is once at global level @ffi.callback("int(int, void *)") def my_global_callback(x, handle): return ffi.from_handle(handle).some_method(x) class Foo(object): def __init__(self): handle = ffi.new_handle(self) self._handle = handle # must be kept alive lib.register_stuff_with_callback_and_voidp_arg(my_global_callback, handle) def some_method(self, x): print "method called!" ``` -------------------------------- ### Build an extension from external C sources Source: https://github.com/python-cffi/cffi/blob/main/doc/source/overview.md Configure CFFI to compile and link against existing C source files. ```python from cffi import FFI ffibuilder = FFI() ffibuilder.cdef("float pi_approx(int n);") ffibuilder.set_source("_pi", # name of the output C extension """ #include "pi.h" """, sources=['pi.c'], # includes pi.c as additional sources libraries=['m']) # on Unix, link with the math library if __name__ == "__main__": ffibuilder.compile(verbose=True) ``` -------------------------------- ### Setting Source with Header Include Source: https://github.com/python-cffi/cffi/blob/main/doc/source/embedding.md Include a header file in the C source for `ffibuilder.set_source()` when embedding. ```python ffibuilder.set_source('module_name', r''' #include "foo.h" ''') ``` -------------------------------- ### Configure Py_LIMITED_API in ffibuilder Source: https://github.com/python-cffi/cffi/blob/main/doc/source/whatsnew.md Pass define_macros to set_source to enable Py_LIMITED_API when building C extensions. ```python ffibuilder.set_source(..., define_macros=[("Py_LIMITED_API", None)]) ``` -------------------------------- ### Assign Initializers to Existing C Data Source: https://github.com/python-cffi/cffi/blob/main/doc/source/using.md Demonstrates assigning Python objects directly to array items or struct fields. ```python # if 'p' is a p[2] = [10, 20] # writes to p[2][0] and p[2][1] # if 'p' is a , and foo_t has fields x, y and z p[0] = {'x': 10, 'z': 20} # writes to p.x and p.z; p.y unmodified # if, on the other hand, foo_t has a field 'char a[5]': p.a = "abc" # writes 'a', 'b', 'c' and '\0'; p.a[4] unmodified ``` -------------------------------- ### ffi.new() Source: https://github.com/python-cffi/cffi/blob/main/doc/source/ref.md Allocates an instance of a specified C type and returns a pointer to it. ```APIDOC ## ffi.new(cdecl, init=None) ### Description Allocates an instance according to the specified C type and returns a pointer to it. The memory is automatically freed when the returned object goes out of scope. ### Parameters - **cdecl** (string) - Required - The C type to allocate (must be a pointer or array). - **init** (any) - Optional - Initializer for the allocated memory. ### Response - **** - A pointer to the allocated memory. ``` -------------------------------- ### Inspect Shared Library Dependencies Source: https://github.com/python-cffi/cffi/blob/main/doc/source/embedding.md Use ldd to verify the paths compiled into the shared object. ```bash ldd libmy_plugin.so ``` -------------------------------- ### Using ffi.new_allocator with a 'with' statement Source: https://github.com/python-cffi/cffi/blob/main/doc/source/ref.md Illustrates the use of ffi.new_allocator() combined with a 'with' statement for automatic memory management, ensuring resources are released at the end of a block. ```APIDOC ## Using ffi.new_allocator() with a 'with' statement ### Description In cffi version 1.12 and later, `ffi.new_allocator()` can be used with a `with` statement. This pattern ensures that the custom free function (or the default one) is called automatically upon exiting the `with` block, similar to how Python's context managers handle resource cleanup. ### Method Use `ffi.new_allocator()` and the `with` statement. ### Endpoint N/A (Internal CFFI usage) ### Parameters N/A ### Request Example ```python from cffi import FFI ffi = FFI() lib = ffi.dlopen(None) # Load the C standard library ffi.cdef("void *malloc(size_t size); void free(void *ptr);") # Define a custom allocator at the global level my_new = ffi.new_allocator(lib.malloc, lib.free) n = 5 # Use the custom allocator within a 'with' statement with my_new("int[]", n) as my_array: # my_array is allocated and will be freed automatically for i in range(n): my_array[i] = i * 2 print(my_array[:n]) # Memory is guaranteed to be freed here ``` ### Response N/A (This is a code example for memory management, not an API endpoint response.) ``` -------------------------------- ### Execute build script Source: https://github.com/python-cffi/cffi/blob/main/doc/source/overview.md Command to trigger the CFFI build process. ```shell python pi_extension_build.py ``` -------------------------------- ### Initialize Arrays with Unspecified Length Source: https://github.com/python-cffi/cffi/blob/main/doc/source/using.md Demonstrates creating arrays where the length is derived from the initializer. ```python int array[] = { 1, 2, 3, 4 }; // C syntax array = ffi.new("int[]", [1, 2, 3, 4]) # CFFI equivalent ``` -------------------------------- ### Pass char** Arguments to C Functions Source: https://github.com/python-cffi/cffi/blob/main/doc/source/using.md Demonstrates the correct way to pass an array of strings to a C function by explicitly creating char[] objects. ```python lib.main_like(2, [ffi.new("char[]", "arg0"), ffi.new("char[]", "arg1")]) ``` -------------------------------- ### Embed Python in C library Source: https://github.com/python-cffi/cffi/blob/main/doc/source/overview.md Creates a shared library that initializes Python and exposes functions to C. ```python import cffi ffibuilder = cffi.FFI() ffibuilder.embedding_api(""" int do_stuff(int, int); """) ffibuilder.set_source("my_plugin", "") ffibuilder.embedding_init_code(""" from my_plugin import ffi @ffi.def_extern() def do_stuff(x, y): print("adding %d and %d" % (x, y)) return x + y """) ffibuilder.compile(target="plugin-1.5.*", verbose=True) ``` -------------------------------- ### Define and compile a C extension with CFFI Source: https://github.com/python-cffi/cffi/blob/main/doc/source/overview.md Use ffibuilder to define C sources and declarations, then compile them into a Python extension module. ```python from cffi import FFI ffibuilder = FFI() ffibuilder.set_source("_example", r""" // passed to the real C compiler, // contains implementation of things declared in cdef() #include #include // We can also define custom wrappers or other functions // here (this is an example only): static struct passwd *get_pw_for_root(void) { return getpwuid(0); } """, libraries=[]) # or a list of libraries to link with # (more arguments like setup.py's Extension class: # include_dirs=[..], extra_objects=[..], and so on) ffibuilder.cdef(""" // declarations that are shared between Python and C struct passwd { char *pw_name; ...; // literally dot-dot-dot }; struct passwd *getpwuid(int uid); // defined in struct passwd *get_pw_for_root(void); // defined in set_source() """) if __name__ == "__main__": ffibuilder.compile(verbose=True) ``` -------------------------------- ### Import generated or verified modules Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md Main program logic to import the generated module or fall back to verification. ```python try: from package._foo import ffi, lib except ImportError: from package.foo_build import ffi, C_HEADER_SRC, C_KEYWORDS lib = ffi.verify(C_HEADER_SRC, **C_KEYWORDS) ``` -------------------------------- ### Use CFFI ABI module Source: https://github.com/python-cffi/cffi/blob/main/doc/source/overview.md Loads the standard C library and calls a function using the generated ABI module. ```python from _simple_example import ffi lib = ffi.dlopen(None) # Unix: open the standard C library #import ctypes.util # or, try this on Windows: #lib = ffi.dlopen(ctypes.util.find_library("c")) lib.printf(b"hi there, number %d\n", ffi.cast("int", 2)) ``` -------------------------------- ### ffibuilder.emit_c_code() Source: https://github.com/python-cffi/cffi/blob/main/doc/source/cdef.md Generates the .c file for API mode without compiling it. ```APIDOC ## ffibuilder.emit_c_code(filename) ### Description Generates the .c file for API mode without performing compilation. Useful for integration with external build systems. ### Parameters #### Path Parameters - **filename** (string or file-like object) - Required - The path to the file to write or a file-like object. ```