diff options
Diffstat (limited to 'zend')
-rw-r--r-- | zend/classimpl.cpp | 6 | ||||
-rw-r--r-- | zend/classimpl.h | 14 | ||||
-rw-r--r-- | zend/extensionimpl.cpp | 2 | ||||
-rw-r--r-- | zend/function.cpp | 49 | ||||
-rw-r--r-- | zend/functor.h | 61 | ||||
-rw-r--r-- | zend/includes.h | 4 | ||||
-rw-r--r-- | zend/namespace.cpp | 12 | ||||
-rw-r--r-- | zend/nativefunction.h (renamed from zend/function.h) | 20 | ||||
-rw-r--r-- | zend/object.cpp | 35 |
9 files changed, 181 insertions, 22 deletions
diff --git a/zend/classimpl.cpp b/zend/classimpl.cpp index e42605e..fa1aa60 100644 --- a/zend/classimpl.cpp +++ b/zend/classimpl.cpp @@ -1344,8 +1344,9 @@ const struct _zend_function_entry *ClassImpl::entries() * @param base the c++ class object created in the extension * @param prefix namespace prefix * @param tsrm_ls + * @return zend_class_entry */ -void ClassImpl::initialize(ClassBase *base, const std::string &prefix TSRMLS_DC) +zend_class_entry *ClassImpl::initialize(ClassBase *base, const std::string &prefix TSRMLS_DC) { // store base pointer _base = base; @@ -1442,6 +1443,9 @@ void ClassImpl::initialize(ClassBase *base, const std::string &prefix TSRMLS_DC) // declare all member variables for (auto &member : _members) member->initialize(_entry TSRMLS_CC); + + // done + return _entry; } /** diff --git a/zend/classimpl.h b/zend/classimpl.h index 26cf030..32f0e1f 100644 --- a/zend/classimpl.h +++ b/zend/classimpl.h @@ -140,6 +140,15 @@ public: } /** + * The class-entry + * @return zend_class_entry + */ + struct _zend_class_entry *entry() const + { + return _entry; + } + + /** * Initialize the class, given its name * * The module functions are registered on module startup, but classes are @@ -150,9 +159,10 @@ public: * * @param base The extension C++ class * @param ns Namespace name - * @param tsrm_ls + * @param tsrm_ls + * @return zend_class_entry */ - void initialize(ClassBase *base, const std::string &ns TSRMLS_DC); + struct _zend_class_entry *initialize(ClassBase *base, const std::string &ns TSRMLS_DC); /** * Static member functions to create or clone objects based on this class diff --git a/zend/extensionimpl.cpp b/zend/extensionimpl.cpp index f073acf..262ecdb 100644 --- a/zend/extensionimpl.cpp +++ b/zend/extensionimpl.cpp @@ -298,7 +298,7 @@ zend_module_entry *ExtensionImpl::module() int i = 0; // apply a function to each function - _data->functions([&i, entries](const std::string &prefix, Function &function) { + _data->functions([&i, entries](const std::string &prefix, NativeFunction &function) { // initialize the function function.initialize(prefix, &entries[i]); diff --git a/zend/function.cpp b/zend/function.cpp new file mode 100644 index 0000000..789175e --- /dev/null +++ b/zend/function.cpp @@ -0,0 +1,49 @@ +/** + * Function.cpp + * + * Implementation file for the Function class + * + * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> + * @copyright 2015 Copernica BV + */ + +/** + * Dependencies + */ +#include "includes.h" + +/** + * Set up namespace + */ +namespace Php { + +/** + * Function returns a pointer to the class-entry of the Functor class + * @return zend_class_entry + */ +zend_class_entry *Function::entry() +{ + // and the actual class entry + static zend_class_entry *entry = nullptr; + + // is the class entry already valid? + if (entry) return entry; + + // construct functor object + static std::unique_ptr<ClassBase> functor(new Class<Functor>("Functor")); + + // initialize the functor class + return entry = functor->implementation()->initialize(functor.get(), "" TSRMLS_CC); +} + +/** + * Constructor + * @param function The function to be wrapped + */ +Function::Function(const std::function<Php::Value(Php::Parameters&)> &function) : Value(Object(entry(), new Functor(function))) {} + +/** + * End of namespace + */ +} + diff --git a/zend/functor.h b/zend/functor.h new file mode 100644 index 0000000..7d5bef5 --- /dev/null +++ b/zend/functor.h @@ -0,0 +1,61 @@ +/** + * Functor.h + * + * We want to be able to wrap a std::function in an object and pass + * that to PHP. The normal "Closure" class from the Zend engine + * would be very suitable for that. However, the Zend engine does + * not really allow us to add a secret pointer to such closure object. + * + * Therefore, we create our own Closure class, this time using PHP-CPP + * code, to wrap a std::function. + * + * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> + * @copyright 2015 Copernica BV + */ + +/** + * Set up namespace + */ +namespace Php { + +/** + * Class definition + */ +class Functor : public Base +{ +public: + /** + * Constructor + * @param function The function to wrap + */ + Functor(const std::function<Value(Parameters ¶ms)> &function) : _function(function) {} + + /** + * Destructor + */ + virtual ~Functor() {} + + /** + * Invoke the functor + * @param params + * @return Value + */ + Value __invoke(Parameters ¶ms) const + { + // pass on to the function + return _function(params); + } + +private: + /** + * The std::function that is wrapped in PHP code + * @var std::function + */ + const std::function<Value(Parameters ¶ms)> _function; +}; + +/** + * End of namespace + */ +} + diff --git a/zend/includes.h b/zend/includes.h index 1552778..83b1086 100644 --- a/zend/includes.h +++ b/zend/includes.h @@ -82,6 +82,7 @@ #include "../include/call.h" #include "../include/script.h" #include "../include/file.h" +#include "../include/function.h" /** * Common header files for internal use only @@ -94,7 +95,7 @@ */ #include "init.h" #include "callable.h" -#include "function.h" +#include "nativefunction.h" #include "method.h" #include "member.h" #include "nullmember.h" @@ -118,6 +119,7 @@ #include "compileroptions.h" #include "executestate.h" #include "opcodes.h" +#include "functor.h" #ifndef ZVAL_COPY_VALUE #define ZVAL_COPY_VALUE(z, v) \ diff --git a/zend/namespace.cpp b/zend/namespace.cpp index 9274bf0..893f2f0 100644 --- a/zend/namespace.cpp +++ b/zend/namespace.cpp @@ -26,7 +26,7 @@ Namespace &Namespace::add(const char *name, const native_callback_0 &function, c if (locked()) return *this; // add a function - _functions.push_back(std::make_shared<Function>(name, function, arguments)); + _functions.push_back(std::make_shared<NativeFunction>(name, function, arguments)); // allow chaining return *this; @@ -45,7 +45,7 @@ Namespace &Namespace::add(const char *name, const native_callback_1 &function, c if (locked()) return *this; // add a function - _functions.push_back(std::make_shared<Function>(name, function, arguments)); + _functions.push_back(std::make_shared<NativeFunction>(name, function, arguments)); // allow chaining return *this; @@ -64,7 +64,7 @@ Namespace &Namespace::add(const char *name, const native_callback_2 &function, c if (locked()) return *this; // add a function - _functions.push_back(std::make_shared<Function>(name, function, arguments)); + _functions.push_back(std::make_shared<NativeFunction>(name, function, arguments)); // allow chaining return *this; @@ -83,7 +83,7 @@ Namespace &Namespace::add(const char *name, const native_callback_3 &function, c if (locked()) return *this; // add a function - _functions.push_back(std::make_shared<Function>(name, function, arguments)); + _functions.push_back(std::make_shared<NativeFunction>(name, function, arguments)); // allow chaining return *this; @@ -97,13 +97,13 @@ Namespace &Namespace::add(const char *name, const native_callback_3 &function, c * * @param callback */ -void Namespace::functions(const std::function<void(const std::string &ns, Function &func)> &callback) +void Namespace::functions(const std::function<void(const std::string &ns, NativeFunction &func)> &callback) { // loop through the functions, and apply the callback for (auto &function : _functions) callback(_name, *function); // loop through the other namespaces - for (auto &ns : _namespaces) ns->functions([this, callback](const std::string &ns, Function &func) { + for (auto &ns : _namespaces) ns->functions([this, callback](const std::string &ns, NativeFunction &func) { // if this is the root namespace, we don't have to change the prefix if (_name.size() == 0) return callback(ns, func); diff --git a/zend/function.h b/zend/nativefunction.h index 4c34ac7..073e69b 100644 --- a/zend/function.h +++ b/zend/nativefunction.h @@ -1,11 +1,11 @@ /** - * Function.h + * NativeFunction.h * * The Function class is an extension of the Callable class that * forwards the function call directly to a native function in C/C++ * * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com> - * @copyright 2013 Copernica BV + * @copyright 2013-2015 Copernica BV */ /** @@ -16,7 +16,7 @@ namespace Php { /** * Class definition */ -class Function : public Callable +class NativeFunction : public Callable { public: /** @@ -24,27 +24,27 @@ public: * @param name Function name * @param function The native C function */ - Function(const char *name, const native_callback_0 &function, const Arguments &arguments = {}) : Callable(name, arguments), _type(0) { _function.f0 = function; } - Function(const char *name, const native_callback_1 &function, const Arguments &arguments = {}) : Callable(name, arguments), _type(1) { _function.f1 = function; } - Function(const char *name, const native_callback_2 &function, const Arguments &arguments = {}) : Callable(name, arguments), _type(2) { _function.f2 = function; } - Function(const char *name, const native_callback_3 &function, const Arguments &arguments = {}) : Callable(name, arguments), _type(3) { _function.f3 = function; } + NativeFunction(const char *name, const native_callback_0 &function, const Arguments &arguments = {}) : Callable(name, arguments), _type(0) { _function.f0 = function; } + NativeFunction(const char *name, const native_callback_1 &function, const Arguments &arguments = {}) : Callable(name, arguments), _type(1) { _function.f1 = function; } + NativeFunction(const char *name, const native_callback_2 &function, const Arguments &arguments = {}) : Callable(name, arguments), _type(2) { _function.f2 = function; } + NativeFunction(const char *name, const native_callback_3 &function, const Arguments &arguments = {}) : Callable(name, arguments), _type(3) { _function.f3 = function; } /** * Copy constructor * @param that */ - Function(const Function &that) : Callable(that), _function(that._function), _type(that._type) {} + NativeFunction(const NativeFunction &that) : Callable(that), _function(that._function), _type(that._type) {} /** * Move constructor * @param that */ - Function(Function &&that) : Callable(std::move(that)), _function(that._function), _type(that._type) {} + NativeFunction(NativeFunction &&that) : Callable(std::move(that)), _function(that._function), _type(that._type) {} /** * Destructor */ - virtual ~Function() {} + virtual ~NativeFunction() {} /** * Method that gets called every time the function is executed diff --git a/zend/object.cpp b/zend/object.cpp index 22431fe..7da8339 100644 --- a/zend/object.cpp +++ b/zend/object.cpp @@ -15,7 +15,7 @@ namespace Php { * Constructor to create a new instance of a builtin class * * @param name Name of the class to instantiate - * @param base Implementation of the class + * @param base The C++ object to wrap */ Object::Object(const char *name, Base *base) : Value() { @@ -54,6 +54,39 @@ Object::Object(const char *name, Base *base) : Value() } /** + * Constructor in case the class entry is already known + * + * @param entry Class entry + * @param base The C++ object to wrap + */ +Object::Object(zend_class_entry *entry, Base *base) : Value() +{ + // does the object already have a handle? + if (base->implementation()) + { + // the object is already instantiated, we can assign it to this object + operator=(Value(base)); + } + else + { + // we need the tsrm_ls variable + TSRMLS_FETCH(); + + // construct an implementation (this will also set the implementation + // member in the base object), this is a self-destructing object that + // will be destructed when the last reference to it has been removed, + // we already set the reference to zero + new ObjectImpl(entry, base, 0 TSRMLS_CC); + + // now we can store it + operator=(Value(base)); + + // install the object handlers + Z_OBJVAL_P(_val).handlers = ClassImpl::objectHandlers(entry); + } +} + +/** * Copy constructor is valid if the passed in object is also an object, * or when it is a string holding a classname * @param that An other object |