summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-08 11:41:00 +0100
committerEmiel Bruijntjes <emiel.bruijntjes@copernica.com>2014-03-08 11:41:00 +0100
commit5b93d44d2a05b3648ec13ae1f076e224d63287d5 (patch)
tree87e9566f8bf6e02105690750df618a1194eee9b0
parent8b94e46c8f044a21c18435525da84bee28594d1a (diff)
introduced Php::call() call function to make builtin, and user space functions callable from C++ space
-rw-r--r--include/call.h54
-rw-r--r--include/globals.h29
-rw-r--r--phpcpp.h1
-rw-r--r--src/globals.cpp230
-rw-r--r--src/includes.h1
-rw-r--r--src/value.cpp19
6 files changed, 62 insertions, 272 deletions
diff --git a/include/call.h b/include/call.h
new file mode 100644
index 0000000..bae0a0a
--- /dev/null
+++ b/include/call.h
@@ -0,0 +1,54 @@
+/**
+ * Call.h
+ *
+ * This file holds a function to call a PHP function
+ *
+ * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
+ * @copyright 2014 Copernica BV
+ */
+
+/**
+ * Set up namespace
+ */
+namespace Php {
+
+/**
+ * Call a function in PHP
+ * @param name Name of the function to call
+ * @param params Variable number of parameters
+ * @return Value
+ */
+template <typename ...Params>
+Value call(const char *name, Params&&... params)
+{
+ // the name can be turned into a Php::Value object, which implements
+ // the operator () method to call it
+ Value function(name);
+
+ // invoke the operator ()
+ return function(std::forward<Params>(params)...);
+}
+
+/**
+ * Long list of simply-forwarded function calls
+ *
+ * Most functions in this list are forwarded to the call() method described
+ * above, which of course is slower than necessary, because they will have to
+ * pass the entire zend engine to look up the actual implementation, while a
+ * direct call the C implementation was possible too. The reason for this is
+ * that we are lazy - if you feel like looking up the actual implementation for
+ * each function in the PHP source, your support is more than welcome.
+ *
+ * But since it is a stupid idea to call a PHP function from your extension
+ * anyway (that's what people write extension for: to get away from PHP and
+ * make the code run on the highway), it is not expected that these functions
+ * are going to be used very often anyway.
+ */
+inline Value array_keys(const Value &value) { return call("array_keys", value); }
+inline Value array_values(const Value &value) { return call("array_values", value); }
+
+/**
+ * End of namespace
+ */
+}
+
diff --git a/include/globals.h b/include/globals.h
index 6faeb8a..0278c88 100644
--- a/include/globals.h
+++ b/include/globals.h
@@ -53,35 +53,8 @@ public:
*/
Global operator[](const std::string &name);
- /**
- * Call a function in PHP
- * We have ten variants of this function, depending on the number of parameters
- * @param name Name of the function
- * @return Value
- */
- Value call(const Value &name);
- Value call(const Value &name, Value p0);
- Value call(const Value &name, Value p0, Value p1);
- Value call(const Value &name, Value p0, Value p1, Value p2);
- Value call(const Value &name, Value p0, Value p1, Value p2, Value p3);
- Value call(const Value &name, Value p0, Value p1, Value p2, Value p3, Value p4);
- Value call(const Value &name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5);
- Value call(const Value &name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6);
- Value call(const Value &name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6, Value p7);
- Value call(const Value &name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6, Value p7, Value p8);
- Value call(const Value &name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6, Value p7, Value p8, Value p9);
-
private:
/**
- * Call function with a number of parameters
- * @param name Function name
- * @param argc Number of parameters
- * @param argv The parameters
- * @return Value
- */
- Value exec(const Value &name, int argc, struct _zval_struct ***params);
-
- /**
* Constructor
*/
Globals() {}
@@ -98,7 +71,7 @@ public:
* We always have one instance
* @var Globals
*/
-extern Globals &globals;
+extern Globals &GLOBALS;
/**
* End of namespace
diff --git a/phpcpp.h b/phpcpp.h
index 74e65fd..207d329 100644
--- a/phpcpp.h
+++ b/phpcpp.h
@@ -50,6 +50,7 @@
#include <phpcpp/interface.h>
#include <phpcpp/namespace.h>
#include <phpcpp/extension.h>
+#include <phpcpp/call.h>
/**
* Macro to export a function
diff --git a/src/globals.cpp b/src/globals.cpp
index 23803a5..6c7af86 100644
--- a/src/globals.cpp
+++ b/src/globals.cpp
@@ -27,7 +27,7 @@ Globals &Globals::instance()
* The one and only instance
* @var Globals
*/
-Globals &globals = Globals::instance();
+Globals &GLOBALS = Globals::instance();
/**
* Get access to a global variable
@@ -80,234 +80,6 @@ Global Globals::operator[](const std::string &name)
}
/**
- * Call function with a number of parameters
- * @param name Function name
- * @param argc Number of parameters
- * @param argv The parameters
- * @return Value
- */
-Value Globals::exec(const Value &name, int argc, zval ***params)
-{
- // the return zval
- zval *retval = nullptr;
-
- // call the function
- if (call_user_function_ex(CG(function_table), NULL, name._val, &retval, argc, params, 1, NULL) != SUCCESS) return nullptr;
-
- // was a value returned?
- if (retval) return Value(retval);
-
- // no value was returned, return NULL
- return nullptr;
-}
-
-/**
- * Call a function in PHP that does not have any parameters
- * @param name Name of the function
- * @return Value
- */
-Value Globals::call(const Value &name)
-{
- // call with zero parameters
- return exec(name, 0, NULL);
-}
-
-/**
- * Call a function in PHP
- * @param name Name of the function
- * @param p0 The first parameter
- * @return Value
- */
-Value Globals::call(const Value &name, Value p0)
-{
- // array of parameters
- zval **params[1] = { &p0._val };
-
- // call the function
- return exec(name, 1, params);
-}
-
-/**
- * Call a function in PHP
- * @param name Name of the function
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @return Value
- */
-Value Globals::call(const Value &name, Value p0, Value p1)
-{
- // array of parameters
- zval **params[2] = { &p0._val, &p1._val };
-
- // call the function
- return exec(name, 2, params);
-}
-
-/**
- * Call a function in PHP
- * @param name Name of the function
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @return Value
- */
-Value Globals::call(const Value &name, Value p0, Value p1, Value p2)
-{
- // array of parameters
- zval **params[3] = { &p0._val, &p1._val, &p2._val };
-
- // call the function
- return exec(name, 3, params);
-}
-
-/**
- * Call a function in PHP
- * @param name Name of the function
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @param p3 The fourth parameter
- * @return Value
- */
-Value Globals::call(const Value &name, Value p0, Value p1, Value p2, Value p3)
-{
- // array of parameters
- zval **params[4] = { &p0._val, &p1._val, &p2._val, &p3._val };
-
- // call the function
- return exec(name, 4, params);
-}
-
-/**
- * Call a function in PHP
- * @param name Name of the function
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @param p3 The fourth parameter
- * @param p4 The fifth parameter
- * @return Value
- */
-Value Globals::call(const Value &name, Value p0, Value p1, Value p2, Value p3, Value p4)
-{
- // array of parameters
- zval **params[5] = { &p0._val, &p1._val, &p2._val, &p3._val, &p4._val };
-
- // call the function
- return exec(name, 5, params);
-}
-
-/**
- * Call a function in PHP
- * @param name Name of the function
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @param p3 The fourth parameter
- * @param p4 The fifth parameter
- * @param p5 The sixth parameter
- * @return Value
- */
-Value Globals::call(const Value &name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5)
-{
- // array of parameters
- zval **params[6] = { &p0._val, &p1._val, &p2._val, &p3._val, &p4._val, &p5._val };
-
- // call the function
- return exec(name, 6, params);
-}
-
-/**
- * Call a function in PHP
- * @param name Name of the function
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @param p3 The fourth parameter
- * @param p4 The fifth parameter
- * @param p5 The sixth parameter
- * @param p6 The seventh parameter
- * @return Value
- */
-Value Globals::call(const Value &name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6)
-{
- // array of parameters
- zval **params[7] = { &p0._val, &p1._val, &p2._val, &p3._val, &p4._val, &p5._val, &p6._val };
-
- // call the function
- return exec(name, 7, params);
-}
-
-/**
- * Call a function in PHP
- * @param name Name of the function
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @param p3 The fourth parameter
- * @param p4 The fifth parameter
- * @param p5 The sixth parameter
- * @param p6 The seventh parameter
- * @param p7 The eight parameter
- * @return Value
- */
-Value Globals::call(const Value &name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6, Value p7)
-{
- // array of parameters
- zval **params[8] = { &p0._val, &p1._val, &p2._val, &p3._val, &p4._val, &p5._val, &p6._val, &p7._val };
-
- // call the function
- return exec(name, 8, params);
-}
-
-/**
- * Call a function in PHP
- * @param name Name of the function
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @param p3 The fourth parameter
- * @param p4 The fifth parameter
- * @param p5 The sixth parameter
- * @param p6 The seventh parameter
- * @param p7 The eight parameter
- * @param p8 The nineth parameter
- * @return Value
- */
-Value Globals::call(const Value &name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6, Value p7, Value p8)
-{
- // array of parameters
- zval **params[9] = { &p0._val, &p1._val, &p2._val, &p3._val, &p4._val, &p5._val, &p6._val, &p7._val, &p8._val };
-
- // call the function
- return exec(name, 9, params);
-}
-
-/**
- * Call a function in PHP
- * @param name Name of the function
- * @param p0 The first parameter
- * @param p1 The second parameter
- * @param p2 The third parameter
- * @param p3 The fourth parameter
- * @param p4 The fifth parameter
- * @param p5 The sixth parameter
- * @param p6 The seventh parameter
- * @param p7 The eight parameter
- * @param p8 The nineth parameter
- * @param p9 The tenth parameter
- * @return Value
- */
-Value Globals::call(const Value &name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6, Value p7, Value p8, Value p9)
-{
- // array of parameters
- zval **params[10] = { &p0._val, &p1._val, &p2._val, &p3._val, &p4._val, &p5._val, &p6._val, &p7._val, &p8._val, &p9._val };
-
- // call the function
- return exec(name, 10, params);
-}
-
-/**
* End of namespace
*/
}
diff --git a/src/includes.h b/src/includes.h
index e9718f3..67a7749 100644
--- a/src/includes.h
+++ b/src/includes.h
@@ -68,6 +68,7 @@
#include "../include/interface.h"
#include "../include/namespace.h"
#include "../include/extension.h"
+#include "../include/call.h"
#include "../include/init.h"
/**
diff --git a/src/value.cpp b/src/value.cpp
index 75a67d4..b775892 100644
--- a/src/value.cpp
+++ b/src/value.cpp
@@ -1174,28 +1174,17 @@ Value Value::exec(int argc, zval ***params) const
*/
Value Value::exec(const char *name, int argc, struct _zval_struct ***params)
{
+ // wrap the name in a Php::Value object to get a zval
+ Value method(name);
+
// the method to call and the return value
- zval *method;
zval *retval;
- // construct the method, this is done similarly to how in PHP we can call
- // a member function using call_user_func: pass in an array with the object
- // and the method to call as the first parameter
- MAKE_STD_ZVAL(method);
- array_init(method);
-
- // add the object and the method to call
- add_index_zval(method, 0, _val);
- add_index_stringl(method, 1, name, strlen(name), 0);
-
// the current exception
zval *oldException = EG(exception);
// call the function
- if (call_user_function_ex(CG(function_table), NULL, method, &retval, argc, params, 1, NULL) != SUCCESS) return nullptr;
-
- // free the method
- FREE_ZVAL(method);
+ if (call_user_function_ex(CG(function_table), &_val, method._val, &retval, argc, params, 1, NULL) != SUCCESS) return nullptr;
// was an exception thrown?
if (oldException != EG(exception)) throw OrigException(EG(exception));