Rust is used to implement a PHP extension

By Edwin Griffin,2015-11-04 18:41
8 views 0
Rust is used to implement a PHP extension

    Rust is used to implement a PHP extension

    I prepared to implement a PHP extension library of Rust,Here,There is a sample, I also for meRust selecta portImplement a PHP extension, two examples are in the same foreign function interface foreign function interface (ffi).I want to make sure to pick a USES the example of string, because the string will contain the number does not introduce additional complexity.

    Before the start of the preparation

    Note: I created a can set up the environmentDocker container

    You will need a PHP development version, if there is one can test it by running: $ which phpize

    Run after which commands can be found as/usr/local/bin/phpize such message, is that it can work normally.Otherwise you will need to run the manager as under CentOS type yum install PHP - devel, under the Debian/Ubuntu can enter apt - get the install php5 - dev for installation.Of course you can also download the source code to manually compile installation.

    Compile the extension

    ourRust libraryExposes a single function, called ext_score it has two * const character parameter of type, returned after a 64 - bit floating-point parameters (or double).In order to build Rust library:

    $ cd rust $ cargo build

    ourPHP extensionsDefines a function called score, it can make our PHP user area and ext_score Rust function "stick" together.In order to build the PHP extension: $ cd php-ext $ phpize $ ./configure --with-score=../rust/target/debug

     $ make $ php -d extension=modules/ -r "var_dump(score('vim', 'vi'));"

    Now we have a working example, so that we can explore each file is actually doing.

    Configuration extensions

    I want to jump straight to the autotools, I think the autoconf is "magic", and around the autoconf PHP packaging is "black magic".However, it is the biggest obstacle to PHP extensions to work, all the things here are dense, need the whole blog into "coma", usually,

through your copy, and paste, it will work, but I will try to conquer this fetter my things.If

    you are successful in this section, the following things will be much simpler.

    If this more than you need, you want to start your extension hard coded,I think so!You

    can jump straight to me after the discussion of the source code.

    This is I wrote for my extension config. M4 files, let's take a look at what is happening



     [whether to enable the "score" extension],

     [ --enable-score Enable "score" extension support]) if test "$PHP_SCORE" != "no"; then

     SEARCH_PATH="/usr/local /usr"


     if test -r $PHP_SCORE/$SEARCH_FOR; then # path given as parameter


     else # search default path list

     AC_MSG_CHECKING([for score files in default path])

     for i in $SEARCH_PATH ; do

     if test -r $i/lib/$SEARCH_FOR; then


     AC_MSG_RESULT(found in $i)




     if test -z "$SCORE_LIB_DIR"; then

     AC_MSG_RESULT([not found])

     AC_MSG_ERROR([Please reinstall the score rust library])


     PHP_CHECK_LIBRARY(score, ext_score,



     AC_DEFINE(HAVE_SCORE, 1, [whether ext_score function exists])


     AC_MSG_ERROR([ext_score function not found in libscore])





     PHP_NEW_EXTENSION(score, score.c, $ext_shared)


    Config. M4 files is a combination, it has some autoconf (AC) functions and some custom PHP functions.Some high level, we are writing to detect which code of our inventory is Rust, and then add the information to the an automatically generated Makefile, it's called the configure script from a generated.Most configuration script will through PHP tools created for us, however, we need to add some extensions specific information.

    Let us begin from extension to the configuration script with PHP_ARG_WITH hook, PHP_ARG_WITH function has three parameters:

    ; The name of the extension.This will be used to determine our

    extension variable's name.In this example, use $PHP_SCORE.

    ; When the. / configure -- with - score runs, human-readable string

    appeared.For example: check whether to enable "score" to

    expand...Yes, to be Shared.

    ; When run/configure -- help, human-readable string appeared.This is

    why string spacing is a bit strange.

    Now run. / configure -- with - score and configuration scripts can know what we are discussing.Next, you need to tell where the configuration script can find our library, so that it can add these details to the Makefile.

    No header file

    PHP assumes that comes with a description the head of the public library function library, but Rust FFI does not provide a header file.If we use a library, for examplegearman , then we would want to/usr/include/gearman. H.Standard PHP config. M4 files will use the header files to check whether a library was installed.In order to solve the problem of lack of header files, we can find a Shared object file: SEARCH_FOR = ". / lib/libscore so ".Now, we can create a function to check the Rust of compatible file, we need to look for it.

    As we begin to check in our common directory libscore. So the Shared object (e.g., / usr and/usr/local), we want to allow to pass. / configure -- with - score = / path/to/covered in the library.The Rust of our library and the combination of the PHP extension is very useful.We can run the cargo build, after can be in/home/Herman/projects/selecta/PHP - ext/target/debug/install libscore. So.Then we can use the. / configure -- with - score = / home/Herman/projects/selecta/PHP - ext/target/debug/configure PHP extensions.When I specify a path like this, the path will be stored in the $PHP_SCORE variable.Over and over again that we don't have to install libraries of Rust.If you do not specify a cover, we can search for some of the common place, can always add more directories to search, for example, / opt/local.

    Link before validation

    We locate a called libscore. So the file, but we need to make sure that it is an effective library file.PHP_CHECK_LIBRARY function is used to verify whether our Shared object contains a known function or a symbol.PHP_CHECK_LIBRARY function with five parameters:

    ; The name of the library.In our case will be converted to - lscore

    at compile time.For example: score conftest cc - o - g - O0 - Wl,

    - rpath, / usr/local/lib - L/usr/local/lib - lscore conftest. C.

    ; Trying to find function name in our library.

    ; If found the function after the action.In our example, we added a

    Makefile to decompiled code of our library, and define HAVE_SCORE

    for use during compilation.

    ; If the function has not been found, need to take action.In our

    example, we threw a mistake with a human-readable error message.

    ; Set up additional library definition.In our example, we make sure

    that the compiler knows where to find the Shared object.

    PHP_ADD_LIBRARY_WTH_PATH function takes the following three parameters:

    ; The name of the library

    ; To the library path

    ; The repository information variable names.We will use the PHP_SUBST

    The final step

    We will success!

    PHP_SUBST function value of a variable is added in the Makefile.

    PHP_NEW_EXTENSION function requires a lot of arguments, but I only use these three:

    ; The name of the extension

    ; Used to construct the extended source, or file list

    ; Should extend dynamic loading or static compilation.$ext_shared

    variables will set the appropriate value for it

    Build your own extensions

    Usually, you can useext_skelProgram to create a PHP extension, however ext_skel generated config. The m4 files made some Rust in violation of the assumptions.But it is still a good place to start, you can change the want to generate the extension directory, then run the ext_skel:

    $ cd /path/to/projects

    $ /path/to/php-src/ext/ext_skel --ext-name=php-rust-ext

    This will create a file/home/Herman/projects/PHP - rust - ext directory: config. M4 config. The w32 tests.I don't have to browse the config. W32 because it is Windows, when they involve the PHP and Windows, I will show the pathetic ignorance.Config. M4 there are a lot of comments to help you, you can use my notes above to make any necessary changes.

    Change the config. The m4

    Once you think properly set config. M4 files, just run phpize command.This program will provide you add a group of automatically generated file directory.At any time. Gitignore them, but they don't check through version control.Most importantly, it creates the configuration file we will be used to generate a Makefile.

    You need to change the config. M4, in order to make your specific extension and library work.If you change the config. M4 files, after will run phpize.If you make a change but then just run the. / configure -- with - score, so will not get any benefits after the change.

    Expand the header file

    This is the PHP extensions of the standard header file, the convention on the use of php_ [extension - the name]. H as its name, in our case, write for php_score. H. #ifndef PHP_SCORE_H

#define PHP_SCORE_H

    #define PHP_SCORE_EXTNAME "score"

    #define PHP_SCORE_EXTVER "1.0"

    #ifdef HAVE_CONFIG_H

    #include "config.h"


    #include "php.h"

    extern zend_module_entry score_module_entry;

    #define phpext_score_ptr &score_module_entry

    // Define our Rust foreign function interface (ffi) here

    extern double ext_score(unsigned char *, unsigned int, char *, unsigned int); #endif

    You can copy/paste, most of them replace SCORE and scroe expand with your name.I choose to define here scores library functions (score libraries functions provides), we tell the compiler defines some external code as a named ext_score function.When we use the function of Rust, this will make our code to compile successfully.Please make sure that lists all of your Rust library public functions.

    The extension source code

    Score. C file is long and most are boring, allscore.cFile here.Let's explore a PHP users area called score function call Rust ext_score function part.



     char *choice;

     int choice_len;

     char *query;

     int query_len;

     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &choice, &choice_len, &query, &query_len) == FAILURE) {



     double s = ext_score(choice, choice_len, query, query_len);



    We announced the new PHP function, they use PHP_FUNCTION macro transfer function name.If you are using the GDB and want to break up this function, the macro will convert it to zif_ [func - name].In our case: it is zif_score.Zif represents the Zend Interface Function (Zend Interface Function).The word you will notice the Zend USES a lot of time because this is the name of PHP virutal machine (and the name of the company founder vm).

    We use the zend_parse_parameters function to parse the function parameter is specified in our user area, in this case, we expect to two strings.This function may seem a bit rough, because it is like that.At the end I will provide some links, to explain in more detail how this function works.In a word, we returned to the two non - null terminated char * values and corresponding to the length of the plastic (ints).

    We can through the string arrive ext_score function, get a result, and then return the value to the PHP user area.We now have a working library Rust end - to - end PHP extensions.

Report this document

For any questions or suggestions please email