### Vector Math Library Example Source: https://context7.com/bohonghuang/cffi-ops/llms.txt A comprehensive example demonstrating the practical application of cffi-ops features within a vector math library context. It includes definitions for vector structures and functions for addition, dot product, and scaling. ```lisp (defpackage vector-math (:use #:cl #:cffi #:cffi-ops) (:export #:vector3-add #:vector3-dot #:vector3-scale)) (in-package #:vector-math) (defcstruct vector3 (x :float) (y :float) (z :float)) (defun vector3-add (out v1 v2) "Add two vectors: out = v1 + v2" (clocally (declare (ctype (:pointer (:struct vector3)) out v1 v2)) (setf (-> out x) (+ (-> v1 x) (-> v2 x)) (-> out y) (+ (-> v1 y) (-> v2 y)) (-> out z) (+ (-> v1 z) (-> v2 z))))) (defun vector3-dot (v1 v2) "Compute dot product: v1 . v2" (clocally (declare (ctype (:pointer (:struct vector3)) v1 v2)) (+ (* (-> v1 x) (-> v2 x)) (* (-> v1 y) (-> v2 y)) (* (-> v1 z) (-> v2 z))))) (defun vector3-scale (out v scalar) "Scale vector: out = v * scalar" (clocally (declare (ctype (:pointer (:struct vector3)) out v)) (setf (-> out x) (* (-> v x) scalar) (-> out y) (* (-> v y) scalar) (-> out z) (* (-> v z) scalar)))) ;; Usage example (defun demo () (clet ((a (foreign-alloca '(:struct vector3))) (b (foreign-alloca '(:struct vector3))) (result (foreign-alloca '(:struct vector3)))) ;; Initialize vectors (setf (-> a x) 1.0 (-> a y) 0.0 (-> a z) 0.0) (setf (-> b x) 0.0 (-> b y) 1.0 (-> b z) 0.0) ;; Compute a + b (vector3-add result a b) (format t "a + b = (~A, ~A, ~A)~%" (-> result x) (-> result y) (-> result z)) ;; Compute dot product (format t "a . b = ~A~%" (vector3-dot a b)) ;; Scale result by 2 (vector3-scale result result 2.0) (format t "2 * (a + b) = (~A, ~A, ~A)~%" (-> result x) (-> result y) (-> result z)))) ;; Output: ;; a + b = (1.0, 1.0, 0.0) ;; a . b = 0.0 ;; 2 * (a + b) = (2.0, 2.0, 0.0) ``` -------------------------------- ### Lisp Code Example using cffi-ops Source: https://github.com/bohonghuang/cffi-ops/blob/master/README.org This Lisp code demonstrates the usage of the cffi-ops library to replicate the functionality of the provided C code. It defines C structures, implements a Vector3 addition function using cffi-ops macros for pointer manipulation, and includes a main function that mirrors the C example's logic with memory allocation and assertions. ```lisp (defpackage cffi-ops-example (:use #:cl #:cffi #:cffi-ops)) (in-package #:cffi-ops-example) (defcstruct vector3 (x :float) (y :float) (z :float)) (defcstruct matrix3 (v1 (:struct vector3)) (v2 (:struct vector3)) (v3 (:struct vector3))) (defun vector3-add (output v1 v2) (clocally (declare (ctype (:pointer (:struct vector3)) output v1 v2)) (setf (-> output x) (+ (-> v1 x) (-> v2 x)) (-> output y) (+ (-> v1 y) (-> v2 y)) (-> output z) (+ (-> v1 z) (-> v2 z))))) (defun main () (clet ((m1 (foreign-alloca '(:array (:struct matrix3) 3)))) (setf (-> ([] m1 0) v1 x) 1.0 (-> ([] m1 0) v1 y) 2.0 (-> ([] m1 0) v1 z) 3.0) (clet* ((m2 ([] m1)) (v1 (& (-> m2 v1))) (v2 (foreign-alloc '(:struct vector3)))) (csetf ([] v2) ([] v1)) (setf (-> v2 x) 3.0 (-> v2 z) 1.0) (vector3-add v1 v1 v2) (assert (= (-> v1 x) 4.0)) (assert (= (-> v1 y) 4.0)) (assert (= (-> v1 z) 4.0)) (foreign-free v2))) ``` -------------------------------- ### C Code Example for cffi-ops Source: https://github.com/bohonghuang/cffi-ops/blob/master/README.org This C code defines structures Vector3 and Matrix3, implements a function to add two Vector3 structures, and demonstrates their usage in the main function with memory allocation, assignment, and assertions. It serves as the basis for the equivalent Lisp code example. ```c #include #include typedef struct { float x; float y; float z; } Vector3; typedef struct { Vector3 v1; Vector3 v2; Vector3 v3; } Matrix3; void Vector3Add(Vector3 *output, const Vector3 *v1, const Vector3 *v2) { output->x = v1->x + v2->x; output->y = v1->y + v2->y; output->z = v1->z + v2->z; } int main(int argc, char *argv[]) { Matrix3 m1[3]; m1[0].v1.x = 1.0; m1[0].v1.y = 2.0; m1[0].v1.z = 3.0; Matrix3 m2 = *m1; Vector3 *v1 = &m2.v1; Vector3 *v2 = malloc(sizeof(Vector3)); ,*v2 = *v1; v2->x = 3.0; v2->z = 1.0; Vector3Add(v1, v1, v2); assert(v1->x == 4.0); assert(v1->y == 4.0); assert(v1->z == 4.0); free(v2); return 0; } ``` -------------------------------- ### Lisp Code Example without cffi-ops Source: https://github.com/bohonghuang/cffi-ops/blob/master/README.org This Lisp code provides the equivalent implementation without using the cffi-ops library. It defines C structures using CFFI's defcstruct and demonstrates manual pointer manipulation for accessing structure members, highlighting the increased verbosity compared to the cffi-ops approach. ```lisp (defpackage cffi-example (:use #:cl #:cffi)) (in-package #:cffi-example) (defcstruct vector3 (x :float) ``` -------------------------------- ### Get Pointer with & Operator Source: https://context7.com/bohonghuang/cffi-ops/llms.txt The `&` operator returns a pointer to a value, mirroring C's address-of operator. It is frequently used in conjunction with the `->` operator to obtain pointers to structure members or array elements. ```lisp (clet ((mat (foreign-alloca '(:struct matrix3)))) (setf (-> mat v1 x) 1.0 (-> mat v1 y) 2.0 (-> mat v1 z) 3.0) ;; Get pointer to v1 member: &mat->v1 (clet ((v1-ptr (& (-> mat v1)))) ;; v1-ptr is now (:pointer (:struct vector3)) (-> v1-ptr x)) ; 1.0 ;; Get pointer to array element: &arr[2] (clet ((arr (foreign-alloca '(:array :float 5)))) (dotimes (i 5) (setf ([] arr i) (float (* i 10)))) (clet ((elem-ptr (& ([] arr 2)))) ;; elem-ptr points to arr[2] ([] elem-ptr)))) ; 20.0 ``` -------------------------------- ### Sequential Variable Binding with clet* Source: https://context7.com/bohonghuang/cffi-ops/llms.txt Explains the `clet*` macro, which provides sequential variable binding similar to Common Lisp's `let*`. This allows subsequent bindings to reference variables defined in earlier bindings within the same scope, facilitating complex data structure manipulations. ```lisp ;; Sequential binding - each variable can use previous ones (clet ((m1 (foreign-alloca '(:array (:struct matrix3) 3)))) (setf (-> ([] m1 0) v1 x) 1.0 (-> ([] m1 0) v1 y) 2.0 (-> ([] m1 0) v1 z) 3.0) (clet* ((m2 ([] m1)) ; m2 = copy of first matrix3 (v1 (& (-> m2 v1))) ; v1 = pointer to m2's v1 member (v2 (foreign-alloc '(:struct vector3)))) ; heap allocated ;; Copy v1's contents to v2 (csetf ([] v2) ([] v1)) ;; Modify v2 (setf (-> v2 x) 3.0 (-> v2 z) 1.0) ;; v1 = (1.0, 2.0, 3.0), v2 = (3.0, 2.0, 1.0) (vector3-add v1 v1 v2) ;; v1 now = (4.0, 4.0, 4.0) (foreign-free v2) (-> v1 x))) ; Returns 4.0 ``` -------------------------------- ### Define C Structures with cffi-ops Source: https://context7.com/bohonghuang/cffi-ops/llms.txt Demonstrates defining C-compatible structures using `defcstruct` from cffi-ops. These definitions are crucial for the library's compile-time type inference mechanism, allowing for C-style access to structure members. ```lisp (defpackage my-ffi-app (:use #:cl #:cffi #:cffi-ops)) (in-package #:my-ffi-app) ;; Define a 3D vector structure (defcstruct vector3 (x :float) (y :float) (z :float)) ;; Define a 3x3 matrix using vector3 structs (defcstruct matrix3 (v1 (:struct vector3)) (v2 (:struct vector3)) (v3 (:struct vector3))) ``` -------------------------------- ### Variable Binding with Type Inference using clet Source: https://context7.com/bohonghuang/cffi-ops/llms.txt Shows how `clet` binds variables to CFFI pointers, inferring types automatically. It handles both stack allocation (`foreign-alloca`) and heap allocation (`foreign-alloc`), simplifying memory management and access to nested structure members using `->` and `[]` operators. ```lisp ;; Allocate array on stack (dynamic-extent) and access elements (clet ((m1 (foreign-alloca '(:array (:struct matrix3) 3)))) ;; m1 is now a pointer to an array of 3 matrix3 structs ;; Access nested struct members using -> and [] (setf (-> ([] m1 0) v1 x) 1.0 (-> ([] m1 0) v1 y) 2.0 (-> ([] m1 0) v1 z) 3.0) ;; Access second matrix (setf (-> ([] m1 1) v2 x) 10.0) ;; m1 is automatically freed when leaving scope (-> ([] m1 0) v1 x)) ; Returns 1.0 ``` -------------------------------- ### Implement memcpy Function Wrapper (Common Lisp) Source: https://github.com/bohonghuang/cffi-ops/blob/master/README.org Provides a Common Lisp wrapper for the C standard library's 'memcpy' function using CFFI. This function copies a specified number of bytes from a source memory location to a destination memory location. It's crucial for low-level memory manipulation when interfacing with C. ```common-lisp (declaim (inline memcpy)) (defcfun "memcpy" :void (dest :pointer) (src :pointer) (n :size)) ``` -------------------------------- ### Main Function: CFFI Structure Manipulation and Memory Ops (Common Lisp) Source: https://github.com/bohonghuang/cffi-ops/blob/master/README.org The main function demonstrates advanced CFFI usage, including allocating foreign memory for 'matrix3' and 'vector3' structures, copying memory using 'memcpy', accessing structure slots, modifying values, performing vector addition, and freeing allocated memory. It includes assertions to verify the correctness of operations. ```common-lisp (defun main () (with-foreign-object (m1 '(:struct matrix3) 3) (with-foreign-slots ((x y z) (foreign-slot-pointer (mem-aptr m1 '(:struct matrix3) 0) '(:struct matrix3) 'v1) (:struct vector3)) (setf x 1.0 y 2.0 z 3.0)) (with-foreign-object (m2 '(:struct matrix3)) (memcpy m2 m1 (foreign-type-size '(:struct matrix3))) (let ((v1 (foreign-slot-pointer m2 '(:struct matrix3) 'v1)) (v2 (foreign-alloc '(:struct vector3)))) (memcpy v2 v1 (foreign-type-size '(:struct vector3))) (with-foreign-slots ((x z) v2 (:struct vector3)) (setf x 3.0 z 1.0)) (vector3-add v1 v1 v2) (with-foreign-slots ((x y z) v1 (:struct vector3)) (assert (= x 4.0)) (assert (= y 4.0)) (assert (= z 4.0))) (foreign-free v2)))))) ``` -------------------------------- ### Define C Structures: vector3 and matrix3 (Common Lisp) Source: https://github.com/bohonghuang/cffi-ops/blob/master/README.org Defines C-compatible structures 'vector3' and 'matrix3' using Common Lisp's CFFI. 'vector3' contains three float members (x, y, z), and 'matrix3' contains three 'vector3' members (v1, v2, v3). These definitions allow Lisp to interact with these structures as if they were native C types. ```common-lisp (defcstruct vector3 (x :float) (y :float) (z :float)) (defcstruct matrix3 (v1 (:struct vector3)) (v2 (:struct vector3)) (v3 (:struct vector3))) ``` -------------------------------- ### Memory Copy Assignment with csetf Source: https://context7.com/bohonghuang/cffi-ops/llms.txt The `csetf` macro facilitates memory copying between CFFI pointers, functioning like struct assignment in C. It requires both arguments to be pointers of the same data type. ```lisp (clet ((src (foreign-alloca '(:struct vector3))) (dst (foreign-alloca '(:struct vector3)))) ;; Initialize source (setf (-> src x) 1.0 (-> src y) 2.0 (-> src z) 3.0) ;; Copy src to dst: *dst = *src (csetf ([] dst) ([] src)) ;; dst now contains (1.0, 2.0, 3.0) (list (-> dst x) (-> dst y) (-> dst z))) ; (1.0 2.0 3.0) ``` -------------------------------- ### Member Access with Arrow Operator (->) Source: https://context7.com/bohonghuang/cffi-ops/llms.txt Details the `->` (arrow) operator in cffi-ops, which provides C-style member access for structs, analogous to both `->` and `.` in C. It supports chained member access and works seamlessly with pointers and values, simplifying the retrieval and modification of struct data. ```lisp (clet ((mat (foreign-alloca '(:struct matrix3)))) ;; Equivalent to C: mat->v1.x = 5.0 (setf (-> mat v1 x) 5.0) ;; Equivalent to C: mat->v2.y = mat->v1.x + 1.0 (setf (-> mat v2 y) (+ (-> mat v1 x) 1.0)) ;; Chained access: mat->v3.z (setf (-> mat v3 z) 9.0) ;; Read values (list (-> mat v1 x) ; 5.0 (-> mat v2 y) ; 6.0 (-> mat v3 z))) ; 9.0 ``` -------------------------------- ### Array Access and Pointer Dereference with [] Source: https://context7.com/bohonghuang/cffi-ops/llms.txt The `[]` operator in cffi-ops handles both array indexing and pointer dereferencing. When provided with an index, it accesses array elements similar to C's `ptr[n]`. When used without an index, it dereferences a pointer, analogous to C's `*ptr`. ```lisp (clet ((arr (foreign-alloca '(:array :float 5)))) ;; Array indexing: arr[0] = 1.0, arr[1] = 2.0, etc. (dotimes (i 5) (setf ([] arr i) (float i))) ;; Read array elements ([] arr 0) ; 0.0 ([] arr 4)) ;; Pointer dereference (no index) (clet ((vec (foreign-alloca '(:struct vector3)))) (setf (-> vec x) 1.0 (-> vec y) 2.0 (-> vec z) 3.0) (clet ((vec-copy ([] vec))) ; Dereference and copy ;; vec-copy is a new pointer to a copy of vec (-> vec-copy x))) ; 1.0 ``` -------------------------------- ### Explicit Type Declaration with cthe Source: https://context7.com/bohonghuang/cffi-ops/llms.txt The `cthe` macro allows for explicit CFFI type declarations, serving a similar purpose to Common Lisp's `the` but specifically for CFFI types. It is valuable when the system's type inference is insufficient. ```lisp ;; Explicitly declare pointer type (defun process-buffer (buffer) (clocally ;; When type cannot be inferred, use cthe (setf (-> (cthe (:pointer (:struct vector3)) buffer) x) 0.0 (-> (cthe (:pointer (:struct vector3)) buffer) y) 0.0 (-> (cthe (:pointer (:struct vector3)) buffer) z) 0.0)) ;; Within clet, use cthe for explicit typing in expressions (clet ((m1 (foreign-alloca '(:array (:array :float 3) 3)))) (loop :for row :below 3 :do (loop :for col :below 3 :do (setf ([] ([] m1 row) col) (+ (* row 3.0) col)))) ;; Reinterpret as matrix3 (clet ((mat ([] (cthe (:pointer (:struct matrix3)) m1)))) (-> (-> mat v1) x))) ; 0.0 ``` -------------------------------- ### Type Declaration Scope with clocally Source: https://context7.com/bohonghuang/cffi-ops/llms.txt Illustrates using the `clocally` macro to establish a lexical scope for declaring CFFI types via `(declare (ctype ...))`. This enables the use of cffi-ops operators (`->`, `[]`, `&`) with automatic type inference for variables within that scope, simplifying pointer manipulation. ```lisp ;; Declare types for function parameters to enable C-style operators (defun vector3-add (output v1 v2) (clocally (declare (ctype (:pointer (:struct vector3)) output v1 v2)) ;; Now -> operator works with automatic type inference (setf (-> output x) (+ (-> v1 x) (-> v2 x)) (-> output y) (+ (-> v1 y) (-> v2 y)) (-> output z) (+ (-> v1 z) (-> v2 z))))) ;; Usage (let ((a (foreign-alloc '(:struct vector3))) (b (foreign-alloc '(:struct vector3))) (result (foreign-alloc '(:struct vector3)))) (clocally (declare (ctype (:pointer (:struct vector3)) a b)) (setf (-> a x) 1.0 (-> a y) 2.0 (-> a z) 3.0) (setf (-> b x) 4.0 (-> b y) 5.0 (-> b z) 6.0)) (vector3-add result a b) ;; result now contains (5.0, 7.0, 9.0) (foreign-free a) (foreign-free b) (foreign-free result)) ``` -------------------------------- ### Vector Addition Function using CFFI (Common Lisp) Source: https://github.com/bohonghuang/cffi-ops/blob/master/README.org Implements a 'vector3-add' function in Common Lisp that adds two 'vector3' structures and stores the result in a third 'vector3' structure. It utilizes 'with-foreign-slots' to access and modify members of C structures allocated in foreign memory, demonstrating direct manipulation of C data. ```common-lisp (defun vector3-add (output v1 v2) (with-foreign-slots (((xout x) (yout y) (zout z)) output (:struct vector3)) (with-foreign-slots (((x1 x) (y1 y) (z1 z)) v1 (:struct vector3)) (with-foreign-slots (((x2 x) (y2 y) (z2 z)) v2 (:struct vector3)) (setf xout (+ x1 x2) yout (+ y1 y2) zout (+ z1 z2)))))) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.