Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proof-of-cencept for calling wasm from php - not great, but probably ok as demo/example code? #519

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
*.o
*.a
*.so
*.txt
*.a.*
*.so.*
build/
.vscode/
.vscode/
136 changes: 136 additions & 0 deletions Examples/extism/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#
# Makefile template
#
# This is an example Makefile that can be used by anyone who is building
# his or her own PHP extensions using the PHP-CPP library.
#
# In the top part of this file we have included variables that can be
# altered to fit your configuration, near the bottom the instructions and
# dependencies for the compiler are defined. The deeper you get into this
# file, the less likely it is that you will have to change anything in it.
#

#
# Name of your extension
#
# This is the name of your extension. Based on this extension name, the
# name of the library file (name.so) and the name of the config file (name.ini)
# are automatically generated
#

NAME = extismcpp


#
# Php.ini directories
#
# In the past, PHP used a single php.ini configuration file. Today, most
# PHP installations use a conf.d directory that holds a set of config files,
# one for each extension. Use this variable to specify this directory.
#

INI_DIR = /etc/php/8.2/cli/conf.d/


#
# The extension dirs
#
# This is normally a directory like /usr/lib/php5/20121221 (based on the
# PHP version that you use. We make use of the command line 'php-config'
# instruction to find out what the extension directory is, you can override
# this with a different fixed directory
#

EXTENSION_DIR = $(shell php-config --extension-dir)


#
# The name of the extension and the name of the .ini file
#
# These two variables are based on the name of the extension. We simply add
# a certain extension to them (.so or .ini)
#

EXTENSION = ${NAME}.so
INI = ${NAME}.ini


#
# Compiler
#
# By default, the GNU C++ compiler is used. If you want to use a different
# compiler, you can change that here. You can change this for both the
# compiler (the program that turns the c++ files into object files) and for
# the linker (the program that links all object files into the single .so
# library file. By default, g++ (the GNU C++ compiler) is used for both.
#

COMPILER = g++
LINKER = g++


#
# Compiler and linker flags
#
# This variable holds the flags that are passed to the compiler. By default,
# we include the -O2 flag. This flag tells the compiler to optimize the code,
# but it makes debugging more difficult. So if you're debugging your application,
# you probably want to remove this -O2 flag. At the same time, you can then
# add the -g flag to instruct the compiler to include debug information in
# the library (but this will make the final libphpcpp.so file much bigger, so
# you want to leave that flag out on production servers).
#
# If your extension depends on other libraries (and it does at least depend on
# one: the PHP-CPP library), you should update the LINKER_DEPENDENCIES variable
# with a list of all flags that should be passed to the linker.
#

COMPILER_FLAGS = -Wall -c -O2 -std=c++11 -fpic -o
LINKER_FLAGS = -shared
LINKER_DEPENDENCIES = -lphpcpp -lextism


#
# Command to remove files, copy files and create directories.
#
# I've never encountered a *nix environment in which these commands do not work.
# So you can probably leave this as it is
#

RM = rm -f
CP = cp -f
MKDIR = mkdir -p


#
# All source files are simply all *.cpp files found in the current directory
#
# A builtin Makefile macro is used to scan the current directory and find
# all source files. The object files are all compiled versions of the source
# file, with the .cpp extension being replaced by .o.
#

SOURCES = $(wildcard *.cpp)
OBJECTS = $(SOURCES:%.cpp=%.o)


#
# From here the build instructions start
#

all: ${OBJECTS} ${EXTENSION}

${EXTENSION}: ${OBJECTS}
${LINKER} ${LINKER_FLAGS} -o $@ ${OBJECTS} ${LINKER_DEPENDENCIES}

${OBJECTS}:
${COMPILER} ${COMPILER_FLAGS} $@ ${@:%.o=%.cpp}

install:
${CP} ${EXTENSION} ${EXTENSION_DIR}
${CP} ${INI} ${INI_DIR}

clean:
${RM} ${EXTENSION} ${OBJECTS}
sudo ${RM} ${EXTENSION_DIR}/${EXTENSION}
sudo ${RM} ${INI_DIR}/${INI}
50 changes: 50 additions & 0 deletions Examples/extism/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
This is just a proof of concept C++ PHP module that loads and runs WASM using https://github.com/extism/extism

as an alternative to https://github.com/extism/php-sdk , which has the following issues:

1 - uses C bindings, not C++

2 - uses php's FFI interface, which itself is a php loadable module like this one, so its got more levels of indirection

3 - PHP FFI is slower that C++ bindings.


This is just barely enough to proove it worked for me, and no more.

Here some output:
```
cd ~/PHP-CPP/Examples/extism
[buzz@qbi-buzz extism]$ make clean ; make ; sudo make install ; time php extismcpp.php
rm -f extismcpp.so extismcpp.o
sudo rm -f /usr/lib/php/20220829/extismcpp.so
sudo rm -f /etc/php/8.2/cli/conf.d//extismcpp.ini
g++ -Wall -c -O2 -std=c++11 -fpic -o extismcpp.o extismcpp.cpp
g++ -shared -o extismcpp.so extismcpp.o -lphpcpp -lextism
cp -f extismcpp.so /usr/lib/php/20220829
cp -f extismcpp.ini /etc/php/8.2/cli/conf.d/
ExtismClass::ExtismClass([no params])
C++ reading wasm...
reading WASM with read_file
done WASM with read_file length:18258
C++ reading wasm done.
calling extism_function_new with hello_world
calling extism_plugin_new with hello function
sending a string to count to count_vowels...
Hello from hello_world C++!
0x7f6583a7135b
hello_world:{"count": 6}[hello output done]
print_plugin_output:{"count": 6}[output done]
count_vowels plugin said:{"count": 6}12
Freeing userdata
------------------------------
LoadWASM count vowels result: {"count": 6}
------------------------------
ExtismClass::__destruct
ExtismClass::~ExtismClass

real 0m0.037s
user 0m0.029s
sys 0m0.008s
```
Yup, so with this... PHP can instantiate extism using its C++ bindings, load a wasm, register a plugin and call a function. I leave it to u to make the interface sane, and not hardcoding a bunch of stuff.

Loading