Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

883 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Swoole Logo

Twitter Discord Build Status License Latest Release Codecov

C++ wrapper for Zend API

简体中文

Requirements

  • PHP 8.2 or later
  • Linux/macOS/Windows
  • GCC 9 or later (with C++17 support)
  • Composer

Installation

Build libphpx.so

# Standard build (Release mode)
cmake .
make -j 4
sudo make install
sudo ldconfig

Debug Mode (for troubleshooting)

# Clean previous builds
cmake --build . --target clean

# Configure Debug mode (includes debug symbols and runtime checks)
cmake -DCMAKE_BUILD_TYPE=Debug .

# Compile
make -j 4
sudo make install
sudo ldconfig

Debug Mode Features:

  • ✅ Generates complete debug symbols
  • ✅ Disables compiler optimizations for easier debugging
  • ✅ Enables runtime error checking
  • ✅ More detailed compilation output

Quick Start

Create a New Extension Project

# Create extension project
composer create-project swoole/phpx-ext test
cd test

Basic Usage Example

Here's a complete example demonstrating modern PHPX extension development:

#include "phpx_ext.h"

// Include auto-generated arginfo header (generated by gen_stub.php)
BEGIN_EXTERN_C()
#include "your_extension_arginfo.h"
END_EXTERN_C()

using namespace php;
using namespace std;

// Method implementation using PHPX_METHOD macro
PHPX_METHOD(MyClass, __construct) {
    // Initialize object properties
    _this.set("name", args[0].toString());
    _this.set("value", args[1].toInt());
    return nullptr;
}

PHPX_METHOD(MyClass, greet) {
    // Access object properties
    auto name = _this.get("name");
    auto value = _this.get("value");
    
    // Return formatted string
    return "Hello, " + name.toStdString() + "! Value: " + to_string(value.toInt());
}

PHPX_METHOD(MyClass, processData) {
    // Work with Array type
    Array input = args[0];
    Array result;
    
    // Iterate and transform
    for (auto &item : input) {
        result.append(item.value.toInt() * 2);
    }
    
    return result;
}

// Function implementation using PHPX_FUNCTION macro
PHPX_FUNCTION(my_extension_func) {
    // Variant - universal type container
    Variant str_var = "Hello PHPX";
    Variant int_var = 42;
    Variant float_var = 3.14159;
    
    // Array operations
    Array arr;
    arr.set("name", "PHPX");
    arr.set("version", 8.2);
    arr.set("features", Array{"C++17", "Type-safe", "Modern API"});
    
    // Object creation and method calls
    Object datetime = newObject("DateTime");
    auto formatted = datetime.call("format", {"Y-m-d H:i:s"});
    
    // Facade functions - direct PHP function calls
    php::var_dump(arr);                    // Debug output
    php::print_r(datetime);                // Print object
    
    // File operations
    auto content = php::file_get_contents("/etc/hosts");
    if (content.isString()) {
        echo("File length: ", content.length(), "\n");
    }
    
    // Array manipulation with references
    Array numbers{1, 2, 3, 4, 5};
    Reference ref = numbers.toReference();
    php::sort(ref);                        // Sort array
    php::array_push(ref, 6, 7, 8);        // Push elements
    
    RETURN_STRING("PHPX Demo Completed!");
}

// Extension entry point
PHPX_EXTENSION() {
    Extension *ext = new Extension("my_extension", "1.0.0");
    
    // Register lifecycle callbacks
    ext->onStart = [ext]() noexcept {
        // Register constants
        ext->registerConstant("MY_EXT_VERSION", 10000);
        
        // Register class with methods
        Class *c = new Class("MyClass");
        c->addProperty("name", "", ZEND_ACC_PUBLIC);
        c->addProperty("value", 0, ZEND_ACC_PUBLIC);
        c->registerFunctions(class_MyClass_methods);  // From arginfo header
        ext->registerClass(c);
        
        // Register standalone functions
        ext->registerFunction(PHPX_FN(my_extension_func));
    };
    
    // PHP info page configuration
    ext->info({"my_extension support", "enabled"},
              {
                  {"author", "Your Name"},
                  {"version", ext->version},
                  {"github", "https://github.com/your/repo"},
              });
    
    return ext;
}

Key Features:

  • PHPX_METHOD/PHPX_FUNCTION: Modern macros for cleaner code
  • Extension/Class API: Object-oriented extension registration
  • Lambda callbacks: Flexible lifecycle management with onStart, onShutdown, etc.
  • Type-safe wrappers: Variant, Array, Object, String classes
  • Facade functions: Direct PHP function calls via php:: namespace
  • Auto-generated arginfo: Use gen_stub.php to generate type information

Generate ArgInfo & Function Entries

php vendor/swoole/phpx/bin/gen_stub.php your_stub_dir

Build Your Extension

cd test
cmake .
make -j 4
make install

Load Your Extension

Edit php.ini and add:

extension=test.so

Test Your Extension

Create a test file test.php:

<?php
echo hello_world() . "\n";
?>

Run it:

php test.php

Expected output:

Hello, World!

Advanced Usage

1. Variant Type Usage

Variant is a universal type container that can hold any PHP value:

#include "phpx.h"

using namespace php;

// Create variants of different types
Variant str_var = "Hello PHPX";
Variant int_var = 42;
Variant float_var = 3.14159;
Variant bool_var = true;
Variant null_var;

// Type checking
if (str_var.isString()) {
    echo("String: ", str_var.toCString());
}

if (int_var.isInt()) {
    echo("Integer: ", int_var.toInt());
}

// Type conversion
auto str = int_var.toString();      // Convert to string
auto num = str_var.toInt();         // Convert to integer (0 if not numeric)

// Comparison
if (str_var.equals("Hello PHPX")) {
    echo("Match!");
}

// Serialization
Variant serialized = str_var.serialize();
Variant unserialized = serialized.unserialize();

2. Array Type Usage

Array provides a C++ wrapper for PHP arrays with rich functionality:

#include "phpx.h"

using namespace php;

// Create arrays
Array arr;
arr.set("name", "PHPX");
arr.set("version", 8.2);
arr.set("features", Array{"C++17", "Type-safe", "Modern API"});

// Initialize with list
Array numbers{1, 2, 3, 4, 5};
Array map{{"key1", "value1"}, {"key2", "value2"}};

// Access elements
auto name = arr.get("name");
auto first = numbers[0];

// Check existence
if (arr.exists("name")) {
    echo("Name exists");
}

// Iterate array
for (auto &item : arr) {
    echo(item.key, ": ", item.value, "\n");
}

// Array operations
arr.append("new_element");          // Add element
arr.del("name");                    // Remove element
auto count = arr.count();           // Get count
auto keys = arr.keys();             // Get all keys

// Nested arrays
Array nested;
nested.set("level1", Array{
    {"level2", Array{"deep_value"}}
});
auto deep = nested.item("level1").item("level2");

// Reference for modification
Array nums{5, 2, 8, 1, 9};
Reference ref = nums.toReference();
php::sort(ref);                     // Sort in place
php::array_push(ref, 10, 11);       // Push elements

3. Object Type Usage

Object wraps PHP objects and provides method calling capabilities:

#include "phpx.h"

using namespace php;

// Create object
Object datetime = newObject("DateTime");

// Call methods
auto formatted = datetime.call("format", {"Y-m-d H:i:s"});
echo("Current time: ", formatted.toCString());

// Set properties
Object stdclass = newObject("stdClass");
stdclass.set("name", "test");
stdclass.set("value", 42);

// Get properties
auto name = stdclass.get("name");
auto value = stdclass.get("value");

// Check property existence
if (stdclass.exists("name")) {
    echo("Property exists");
}

// Create object with constructor arguments
Object arrayObj = newObject("ArrayObject", {
    Array{1, 2, 3, 4, 5}
});

// Call method and get result
auto count = arrayObj.call("count");
echo("Count: ", count.toInt());

// Static method calls
auto result = Object::callStatic("DateTime", "createFromFormat", {
    "Y-m-d", "2024-01-01"
});

4. Facade Encapsulation API

PHPX provides facade functions in the php:: namespace for direct PHP function calls:

#include "phpx.h"
#include "phpx_func.h"

using namespace php;

// Debug and output
php::var_dump(some_variable);           // Debug output
php::print_r(some_variable);            // Print readable
php::echo("Hello", " ", "World");      // Echo strings

// File operations
auto content = php::file_get_contents("/path/to/file.txt");
php::file_put_contents("/path/to/file.txt", "content");

// Array manipulation (requires reference)
Array arr{5, 2, 8, 1, 9};
Reference ref = arr.toReference();

php::sort(ref);                         // Sort array
php::rsort(ref);                        // Reverse sort
php::shuffle(ref);                      // Shuffle
php::array_push(ref, 10, 11);          // Push elements
php::array_pop(ref);                    // Pop element
php::array_shift(ref);                  // Shift element
php::array_unshift(ref, 0);            // Unshift element

// String operations
auto upper = php::strtoupper("hello");
auto lower = php::strtolower("HELLO");
auto length = php::strlen("hello");
auto pos = php::strpos("hello world", "world");

// Math operations
auto max_val = php::max({1, 2, 3, 4, 5});
auto min_val = php::min({1, 2, 3, 4, 5});
auto sum = php::array_sum(Array{1, 2, 3, 4, 5});
auto rand_val = php::rand(1, 100);

// JSON operations
Array data{{"name", "PHPX"}, {"version", 8.2}};
auto json_str = php::json_encode(data);
auto decoded = php::json_decode(json_str, true);

// Other useful functions
php::sleep(2);                          // Sleep 2 seconds
auto time = php::time();                // Current timestamp
auto date = php::date("Y-m-d H:i:s");  // Formatted date

5. Built-in Class Facade Encapsulation

PHPX provides facade classes for popular PHP extensions:

#include "phpx.h"
#include "phpx_class.h"

using namespace php;

// Redis example
Redis redis{};
redis.connect("127.0.0.1", 6379);

// String operations
redis.set("name", "PHPX");
redis.set("version", "8.2");
auto name = redis.get("name");
echo("Name: ", name.toCString());

// Check existence
if (redis.exists("name")) {
    echo("Key exists");
}

// Multiple operations
redis.mset({
    {"key1", "value1"},
    {"key2", "value2"},
    {"key3", "value3"}
});

auto values = redis.mget({"key1", "key2", "key3"});

// List operations
redis.rpush("mylist", "item1");
redis.rpush("mylist", "item2");
auto list_len = redis.llen("mylist");

// Hash operations
redis.hset("user:1", "name", "John");
redis.hset("user:1", "email", "john@example.com");
auto user_name = redis.hget("user:1", "name");

// Set expiration
redis.expire("name", 3600);  // Expire in 1 hour

// Delete keys
redis.del("key1", "key2");

// Close connection
redis.close();

Note: To use Redis facade, ensure the Redis extension is loaded in your PHP environment.

Documentation

For more detailed documentation, please check:

Examples

Check out the examples directory for more comprehensive examples including:

  • Bloom filter implementation
  • Queue data structure
  • RocksDB integration
  • GTK application
  • And more!

Language

License

PHPX is open-sourced software licensed under the Apache License 2.0.

About

C++ wrapper for Zend API

Resources

Stars

863 stars

Watchers

71 watching

Forks

Releases

Used by

Contributors

Languages