Permalink
Browse files

Adding a new php.call() Python function for calling PHP functions.

  • Loading branch information...
1 parent 2a37de3 commit 243bb93966e394fb58f85cbb717db9c34f1083bc @jparise committed Jan 19, 2009
Showing with 101 additions and 9 deletions.
  1. +2 −1 package.php
  2. +9 −7 package.xml
  3. +74 −1 python_php.c
  4. +16 −0 tests/php_call.phpt
View
@@ -9,10 +9,11 @@
$version = '0.9.0a';
$notes = <<<EOT
-- Python Unicode strings are now converted to UTF8-encoded PHP strings.
- Each request now has its own, private interpreter state.
- The new "python.optimize" INI setting controls Python's optimization level.
- Python's sys.stdout and sys.stderr streams are now intercepted.
+- Python Unicode strings are now converted to UTF8-encoded PHP strings.
+- Added a new php.call() Python function for calling PHP functions.
EOT;
$package = new PEAR_PackageFileManager2();
View
@@ -14,7 +14,7 @@
<active>yes</active>
</lead>
<date>2009-01-18</date>
- <time>15:39:48</time>
+ <time>17:49:55</time>
<version>
<release>0.9.0a</release>
<api>0.6.0</api>
@@ -24,10 +24,11 @@
<api>alpha</api>
</stability>
<license>MIT License</license>
- <notes>- Python Unicode strings are now converted to UTF8-encoded PHP strings.
-- Each request now has its own, private interpreter state.
+ <notes>- Each request now has its own, private interpreter state.
- The new &quot;python.optimize&quot; INI setting controls Python&apos;s optimization level.
-- Python&apos;s sys.stdout and sys.stderr streams are now intercepted.</notes>
+- Python&apos;s sys.stdout and sys.stderr streams are now intercepted.
+- Python Unicode strings are now converted to UTF8-encoded PHP strings.
+- Added a new php.call() Python function for calling PHP functions.</notes>
<contents>
<dir baseinstalldir="/" name="/">
<dir name="docs">
@@ -100,10 +101,11 @@
</stability>
<date>2009-01-18</date>
<license>MIT License</license>
- <notes>- Python Unicode strings are now converted to UTF8-encoded PHP strings.
-- Each request now has its own, private interpreter state.
+ <notes>- Each request now has its own, private interpreter state.
- The new &quot;python.optimize&quot; INI setting controls Python&apos;s optimization level.
-- Python&apos;s sys.stdout and sys.stderr streams are now intercepted.</notes>
+- Python&apos;s sys.stdout and sys.stderr streams are now intercepted.
+- Python Unicode strings are now converted to UTF8-encoded PHP strings.
+- Added a new php.call() Python function for calling PHP functions.</notes>
</release>
<release>
<version>
View
@@ -27,6 +27,78 @@
#include "php.h"
#include "php_python_internal.h"
+/* {{{ efree_array
+ */
+static void
+efree_array(zval ***p, int n)
+{
+ int i;
+
+ for (i = 0; i < n; ++i)
+ efree(p[i]);
+
+ efree(p);
+}
+/* }}} */
+
+/* {{{ php_call
+ */
+static PyObject *
+php_call(PyObject *self, PyObject *args)
+{
+ const char *name;
+ int name_len, i, argc;
+ zval ***argv, *lcname, *ret;
+ PyObject *params;
+
+ TSRMLS_FETCH();
+
+ if (!PyArg_ParseTuple(args, "s#|O:call", &name, &name_len, &params))
+ return NULL;
+
+ /* Name entries in the PHP function_table are always lowercased. */
+ MAKE_STD_ZVAL(lcname);
+ ZVAL_STRINGL(lcname, (char *)name, name_len, 1);
+ zend_str_tolower(Z_STRVAL_P(lcname), name_len);
+
+ /* If this isn't a valid PHP function name, we cannot proceed. */
+ if (!zend_hash_exists(CG(function_table), Z_STRVAL_P(lcname), name_len+1)) {
+ PyErr_Format(PyExc_NameError, "Function does not exist: %s",
+ Z_STRVAL_P(lcname));
+ return NULL;
+ }
+
+ /* Convert the parameters into PHP values. */
+ argc = PyTuple_Size(params);
+ argv = emalloc(sizeof(zval **) * argc);
+
+ for (i = 0; i < argc; ++i) {
+ PyObject *item = PyTuple_GetItem(params, i);
+
+ argv[i] = emalloc(sizeof(zval *));
+ MAKE_STD_ZVAL(*argv[i]);
+
+ if (pip_pyobject_to_zval(item, *argv[i] TSRMLS_CC) != SUCCESS) {
+ PyErr_Format(PyExc_ValueError, "Bad argument at index %d", i);
+ efree_array(argv, argc);
+ return NULL;
+ }
+ }
+
+ /* Now we can call the PHP function. */
+ if (call_user_function_ex(CG(function_table), (zval **)NULL, lcname, &ret,
+ argc, argv, 0, NULL TSRMLS_CC) != SUCCESS) {
+ PyErr_Format(PyExc_Exception, "Failed to execute function: %s",
+ Z_STRVAL_P(lcname));
+ efree_array(argv, argc);
+ return NULL;
+ }
+
+ efree_array(argv, argc);
+
+ return pip_zval_to_pyobject(ret TSRMLS_CC);
+}
+/* }}} */
/* {{{ php_var
*/
static PyObject *
@@ -61,8 +133,9 @@ php_version(PyObject *self, PyObject *args)
/* {{{ python_php_methods[]
*/
static PyMethodDef python_php_methods[] = {
- {"version", php_version, METH_NOARGS},
+ {"call", php_call, METH_VARARGS},
{"var", php_var, METH_VARARGS},
+ {"version", php_version, METH_NOARGS},
{NULL, NULL, 0, NULL}
};
/* }}} */
View
@@ -0,0 +1,16 @@
+--TEST--
+Python: php.call()
+--SKIPIF--
+<?php if (!extension_loaded('python')) die("skip\n");
+--FILE--
+<?php
+
+$py = <<<EOT
+import php
+
+print php.call('sha1', ('apple',))
+EOT;
+
+python_exec($py);
+--EXPECT--
+d0be2dc421be4fcd0172e5afceea3970e2f3d940

0 comments on commit 243bb93

Please sign in to comment.