swoole / phpx
C++ wrapper for Zend API
Requires
- league/climate: ^3.10
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.75
- phpunit/phpunit: ^10.0
README
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,Stringclasses - Facade functions: Direct PHP function calls via
php::namespace - Auto-generated arginfo: Use
gen_stub.phpto 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.
