Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Rindow Math Buffer Ffi Laravel Package

rindow/rindow-math-buffer-ffi

A universal one-dimensional buffer for exchanging numeric data between PHP and C/C++ through FFI, designed for math libraries. Provides fast, shared memory access for vectors and matrices across Linux, Windows, and macOS on PHP 8.1 through 8.4.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require rindow/rindow-math-buffer-ffi
    

    Ensure your project uses PHP 8.1+ and runs on Linux/macOS/Windows. As of 1.0.7 the package is tested against PHP 8.5, so it is safe to include in CI matrices targeting the newest runtime.

  2. First Use Case: Buffer Creation

    use Rindow\Math\Buffer\FFI\Buffer;
    
    // Initialize FFI buffer (adjust path to your math library)
    $ffi = FFI::cdef("
        typedef double double_t;
        double_t *malloc(size_t size);
        void free(double_t *ptr);
    ", 'path/to/your/math_library.so');
    
    $buffer = new Buffer($ffi, 10); // Buffer of 10 doubles
    $buffer->fill(0.0); // Fill with zeros
    
  3. Key Entry Points

    • Buffer::create(): Initialize a new buffer.
    • Buffer::fill(): Set all values to a scalar.
    • Buffer::get()/Buffer::set(): Access individual elements.
    • Buffer::toArray()/Buffer::fromArray(): Convert between PHP arrays and FFI buffers.
    • New in 1.0.7: offsetSet() ($buffer[$i] = $value) now enforces strict typing when the buffer dtype is not complex — assigning an object to a real/int buffer is rejected instead of being silently coerced.

Implementation Patterns

Core Workflows

  1. Data Exchange with C Libraries

    // Pass buffer to C function (e.g., BLAS/LAPACK)
    $ffi->my_c_function($buffer->getPointer(), $buffer->getSize());
    
  2. Batch Operations

    // Fill with sequential values
    for ($i = 0; $i < $buffer->getSize(); $i++) {
        $buffer->set($i, $i * 1.5);
    }
    
  3. ArrayAccess-Style Writes (now type-checked)

    $buffer[0] = 1.5;          // scalar — fine for a real buffer
    $buffer[1] = $someObject;  // throws on non-complex dtypes as of 1.0.7
    

    Use offsetSet for ergonomic indexing, but only push objects into buffers whose dtype is a complex type.

  4. Memory Management

    // Explicit cleanup (if not using RAII)
    $buffer->free();
    

Integration Tips

  • Leverage with Rindow Math Libraries Combine with rindow/math for matrix operations:

    use Rindow\Math\Matrix\Matrix;
    
    $matrix = Matrix::create(3, 3);
    $buffer = $matrix->toBuffer(); // Convert to FFI buffer
    
  • Performance Optimization

    • Pre-allocate buffers for repeated operations.
    • Use Buffer::copy() to avoid reallocations.
  • Type Safety Ensure FFI cdef matches the target library’s signatures (e.g., double_t for BLAS). The 1.0.7 offsetSet strictness aligns buffer writes with that same intent — keep your dtype declarations honest so the new checks accept your values.

  • CI Matrix Add PHP 8.5 to your test matrix; it is now an officially exercised runtime. Keep 8.1+ in the matrix for backward compatibility of consumers.


Gotchas and Tips

Pitfalls

  1. offsetSet Strict Object Checks (Behavioral change in 1.0.7)

    • Symptom: $buffer[$i] = $object throws on a buffer whose dtype is not complex; previously it may have been silently accepted or cast.
    • Fix: Only write objects into complex-dtype buffers. For real/int buffers, write scalars or explicitly extract the scalar first:
      $buffer[$i] = $complexValue->getReal(); // real buffer
      // or use a complex-dtype buffer for complex objects
      
    • Migration: Grep your codebase for $buffer[...] = assignments where the right-hand side is an object, and audit the buffer dtype at each site.
  2. FFI Initialization Errors

    • Symptom: FFI::cdef() fails silently or throws cryptic errors.
    • Fix: Verify the library path is correct and the FFI signature matches the C header.
      // Debug: Check if the library loads
      $ffi = FFI::load('math_library.so');
      
  3. Memory Leaks

    • Symptom: Buffer values persist after expected cleanup.
    • Fix: Always call $buffer->free() or use a finally block:
      try {
          $buffer = new Buffer($ffi, 100);
          // ... operations ...
      } finally {
          $buffer->free();
      }
      
  4. Cross-Platform Quirks

    • Windows: Use .dll paths (e.g., 'C:\path\to\lib.dll').
    • macOS/Linux: Ensure library permissions allow FFI access (chmod +r library.so).
  5. PHPUnit Hang (macOS)

    • Workaround: Use a custom GitHub Actions setup or Docker for testing.

Debugging Tips

  • Inspect Buffer Contents
    print_r($buffer->toArray());
    
  • FFI Verbosity Enable FFI debugging in php.ini:
    ffi.debug = 1
    
  • Type-rejection triage: When a write fails after upgrading to 1.0.7, dump the buffer dtype and the value’s type — the strict check only fires for non-complex dtypes with object input.

Extension Points

  1. Custom Buffer Types Extend Buffer to support complex numbers or mixed types:

    class ComplexBuffer extends Buffer {
        public function setComplex(int $index, float $real, float $imag): void {
            $this->set($index * 2, $real);
            $this->set($index * 2 + 1, $imag);
        }
    }
    

    Note that custom subclasses overriding offsetSet should preserve the 1.0.7 strict-check semantics for non-complex dtypes, or document the deviation explicitly.

  2. Integration with Laravel

    • Service Provider: Register FFI buffers as a singleton:
      $this->app->singleton('math.buffer', function ($app) {
          $ffi = FFI::load('vendor/math_library.so');
          return new Buffer($ffi, 1024);
      });
      
    • Facade: Create a MathBuffer facade for cleaner syntax:
      use Illuminate\Support\Facades\Facade;
      
      class MathBuffer extends Facade {
          protected static function getFacadeAccessor() { return 'math.buffer'; }
      }
      
    • Bound singletons are shared mutable state — be aware the new strict offsetSet check applies to every write through the container-resolved instance.
  3. Async Operations Use Swoole or ReactPHP to offload heavy computations to worker processes:

    $buffer = new Buffer($ffi, 1000);
    $worker = new \Swoole\Process(function () use ($buffer) {
        // Heavy math ops here
    });
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin