Permalink
Browse files

Glue Rust to php

Simple example that shows how to write a php extension that uses a Rust
function.
  • Loading branch information...
hjr3 committed Aug 3, 2015
1 parent 710138f commit b48de0ae95618447a5d237bf48e2dbd8ac45e203
Showing with 109 additions and 0 deletions.
  1. +33 −0 php-ext/config.m4
  2. +20 −0 php-ext/php_score.h
  3. +56 −0 php-ext/score.c
View
@@ -0,0 +1,33 @@
+PHP_ARG_WITH(score,
+ [Whether to enable the "score" extension],
+ [ --enable-score Enable "score" extension support])
+
+if test "$PHP_SCORE" != "no"; then
+
+ dnl Explicitly define the location of the library.
+ dnl Production extensions should use the example from ext_skel on how to
+ dnl properly check common library directories for the existence of your
+ dnl libs.
+ SCORE_LIB_DIR=/usr/local/lib
+
+ dnl This is the proper way to check for the existance of a library. But...
+ dnl this creates a simple program that expects a .h file that will define
+ dnl our functions. Rust does not provide that, so it fails. There is
+ dnl probably some autotools magic I can do to make this work, but alas.
+ dnl PHP_CHECK_LIBRARY(score, score_ext,
+ dnl [
+ dnl PHP_ADD_LIBRARY_WITH_PATH(score, $SCORE_LIB_DIR, SCORE_SHARED_LIBADD)
+ dnl AC_DEFINE(HAVE_SCORE, 1, [Whether you have score])
+ dnl ],[
+ dnl AC_MSG_ERROR([ext_score function not found in libscore])
+ dnl ],[
+ dnl -L$SCORE_LIB_DIR -R$SCORE_LIB_DIR
+ dnl ])
+
+ dnl Just blindly assume our libscore.so library exists
+ PHP_ADD_LIBRARY_WITH_PATH(score, $SCORE_LIB_DIR, SCORE_SHARED_LIBADD)
+ -L$SCORE_LIB_DIR -R$SCORE_LIB_DIR
+
+ PHP_SUBST(SCORE_SHARED_LIBADD)
+ PHP_NEW_EXTENSION(score, score.c, $ext_shared)
+fi
View
@@ -0,0 +1,20 @@
+#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"
+#endif
+
+#include "php.h"
+
+extern zend_module_entry score_module_entry;
+#define phpext_score_ptr &score_module_entry
+
+// Because Rust does not provide a .h file to include
+extern double ext_score(char *, char *);
+
+#endif
View
@@ -0,0 +1,56 @@
+#include "php_score.h"
+
+PHP_FUNCTION(score)
+{
+ 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) {
+ return;
+ }
+
+ // PHP does not terminate strings with a nul byte.
+ char *choice_c_str = emalloc(choice_len + 1);
+ strncpy(choice_c_str, choice, choice_len);
+ choice_c_str[choice_len] = '\0';
+
+ char *query_c_str = emalloc(query_len + 1);
+ strncpy(query_c_str, query, query_len);
+ query_c_str[query_len] = '\0';
+
+ double s = ext_score(choice_c_str, query_c_str);
+
+ efree(choice_c_str);
+ efree(query_c_str);
+
+ RETURN_DOUBLE(s);
+}
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_score, 0, 0, 1)
+ ZEND_ARG_INFO(0, choice)
+ ZEND_ARG_INFO(0, query)
+ZEND_END_ARG_INFO()
+
+zend_function_entry php_score_functions[] = {
+ PHP_FE(score, arginfo_score)
+ {NULL, NULL, NULL} /* must be the last line */
+};
+
+zend_module_entry score_module_entry = {
+ STANDARD_MODULE_HEADER,
+ PHP_SCORE_EXTNAME,
+ php_score_functions,
+ NULL, /* minit */
+ NULL, /* mshutdown */
+ NULL, /* rinit */
+ NULL, /* rshutdown */
+ NULL, /* minfo */
+ PHP_SCORE_EXTVER,
+ STANDARD_MODULE_PROPERTIES
+};
+
+#ifdef COMPILE_DL_SCORE
+ZEND_GET_MODULE(score)
+#endif

0 comments on commit b48de0a

Please sign in to comment.