summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Examples/Exceptions/ExceptionCatch/exception.php2
-rw-r--r--Examples/Exceptions/ExceptionCatch/exceptionCatch.cpp8
-rw-r--r--include/origexception.h63
-rw-r--r--phpcpp.h1
-rw-r--r--src/function.cpp7
-rw-r--r--src/includes.h1
-rw-r--r--src/origexception.cpp80
-rw-r--r--src/value.cpp11
8 files changed, 164 insertions, 9 deletions
diff --git a/Examples/Exceptions/ExceptionCatch/exception.php b/Examples/Exceptions/ExceptionCatch/exception.php
index 0fec704..f0bfe90 100644
--- a/Examples/Exceptions/ExceptionCatch/exception.php
+++ b/Examples/Exceptions/ExceptionCatch/exception.php
@@ -14,4 +14,4 @@ my_catch_exception_function(function($a, $b, $c) {
// throw an exception from PHP - the C++ code will catch this exception
throw new Exception("Example exception");
-});}
+});
diff --git a/Examples/Exceptions/ExceptionCatch/exceptionCatch.cpp b/Examples/Exceptions/ExceptionCatch/exceptionCatch.cpp
index a5f7b96..9efdf93 100644
--- a/Examples/Exceptions/ExceptionCatch/exceptionCatch.cpp
+++ b/Examples/Exceptions/ExceptionCatch/exceptionCatch.cpp
@@ -11,6 +11,7 @@
* Libraries used.
*/
#include <phpcpp.h>
+#include <iostream>
/**
* Namespace to use
@@ -39,7 +40,8 @@ void my_catch_exception_function(Php::Parameters &params)
}
catch (Php::Exception &exception)
{
- // @todo handle the exception that was thrown from PHP space
+ // handle the exception that was thrown from PHP space
+ std::cout << "exception caught in CPP code" << std::endl;
}
}
@@ -54,9 +56,7 @@ extern "C"
static Php::Extension extension("my_exception_catch","1.0");
// add function to extension
- extension.add("my_catch_exception_function", my_catch_exception_function, {
- Php::ByVal("callback", Php::callableType);
- });
+ extension.add("my_catch_exception_function", my_catch_exception_function);
// return the extension module
return extension.module();
diff --git a/include/origexception.h b/include/origexception.h
new file mode 100644
index 0000000..bce0945
--- /dev/null
+++ b/include/origexception.h
@@ -0,0 +1,63 @@
+/**
+ * OrigException.h
+ *
+ * Class that wraps around an exception that was thrown by PHP code,
+ * and that could - but not necessarily has to - be caught by C++
+ *
+ * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
+ * @copyright 2013 Copernica BV
+ */
+
+/**
+ * Set up namespace
+ */
+namespace Php {
+
+/**
+ * Class definition
+ */
+class OrigException : public Value, public Exception
+{
+private:
+ /**
+ * Has the exception been restored by the C++ code so that it can be dealt by PHP?
+ * @var boolean
+ */
+ bool _restored;
+
+public:
+ /**
+ * Constructor
+ * @param zval
+ */
+ OrigException(struct _zval_struct *zval);
+
+ /**
+ * Copy constructor
+ * @param exception
+ */
+ OrigException(const OrigException &exception);
+
+ /**
+ * Move constructor
+ * @param exception
+ */
+ OrigException(OrigException &&exception);
+
+ /**
+ * Destructor
+ */
+ virtual ~OrigException();
+
+ /**
+ * Restore the exception - because the exception was not handled by C++ code
+ * @internal
+ */
+ void restore();
+};
+
+/**
+ * End of namespace
+ */
+}
+
diff --git a/phpcpp.h b/phpcpp.h
index 236a93a..77d0156 100644
--- a/phpcpp.h
+++ b/phpcpp.h
@@ -45,6 +45,7 @@
#include <phpcpp/classinfo.h>
#include <phpcpp/extension.h>
#include <phpcpp/exception.h>
+#include <phpcpp/originalexception.h>
/**
* Macro to export a function
diff --git a/src/function.cpp b/src/function.cpp
index cc4315f..3269448 100644
--- a/src/function.cpp
+++ b/src/function.cpp
@@ -43,6 +43,13 @@ void invoke_function(INTERNAL_FUNCTION_PARAMETERS)
// get the result
result = function->invoke(params);
}
+ catch (Php::OrigException &exception)
+ {
+ // we caught an exception that was original thrown by PHP code, and not
+ // processed by C++ code, this means that we're going to restore this
+ // exception so that it can be further handled by PHP
+ exception.restore();
+ }
catch (Php::Exception &exception)
{
// an exception originally thrown by C++ should be passed on to PHP
diff --git a/src/includes.h b/src/includes.h
index 18e9951..933e317 100644
--- a/src/includes.h
+++ b/src/includes.h
@@ -58,6 +58,7 @@
#include "../include/classinfo.h"
#include "../include/extension.h"
#include "../include/exception.h"
+#include "../include/origexception.h"
#include "../include/init.h"
/**
diff --git a/src/origexception.cpp b/src/origexception.cpp
new file mode 100644
index 0000000..299730e
--- /dev/null
+++ b/src/origexception.cpp
@@ -0,0 +1,80 @@
+/**
+ * Implementation of the exception that was originally thrown by PHP
+ * code or the zend engine, and that could or could not be picked
+ * up by C++ code
+ *
+ * @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
+ * @copyright 2013 Copernica BV
+ */
+#include "includes.h"
+
+/**
+ * Set up namespace
+ */
+namespace Php {
+
+/**
+ * Constructor
+ * @param zval
+ */
+OrigException::OrigException(struct _zval_struct *zval) :
+ Value(zval),
+ Exception("OrigException"),
+ _restored(false)
+{
+ std::cout << "save the exception" << std::endl;
+
+ // save the exception
+ zend_exception_save();
+}
+
+/**
+ * Copy constructor
+ * @param exception
+ */
+OrigException::OrigException(const OrigException &exception) :
+ Value(exception),
+ Exception("OrigException"),
+ _restored(exception._restored) {}
+
+/**
+ * Move constructor
+ * @param exception
+ */
+OrigException::OrigException(OrigException &&exception) :
+ Value(std::move(exception)),
+ Exception("OrigException"),
+ _restored(exception._restored) {}
+
+/**
+ * Destructor
+ */
+OrigException::~OrigException()
+{
+ // skip if the exception was restored
+ if (_restored) return;
+
+ // clean up the exception
+ zend_clear_exception();
+}
+
+/**
+ * Restore the exception
+ * @internal
+ */
+void OrigException::restore()
+{
+ std::cout << "restore the exception" << std::endl;
+
+ // restore the exception
+ zend_exception_restore();
+
+ // mark exception as restored
+ _restored = true;
+}
+
+/**
+ * End of namespace
+ */
+}
+
diff --git a/src/value.cpp b/src/value.cpp
index 194934d..49c9c2b 100644
--- a/src/value.cpp
+++ b/src/value.cpp
@@ -868,14 +868,17 @@ Value Value::exec(int argc, zval ***params)
// the return zval
zval *retval = nullptr;
+ // the current exception
+ zval *oldException = EG(exception);
+
// call the function
if (call_user_function_ex(CG(function_table), NULL, _val, &retval, argc, params, 1, NULL) != SUCCESS) return nullptr;
- // was a value returned?
- if (retval) return Value(retval);
+ // was an exception thrown?
+ if (oldException != EG(exception)) throw OrigException(EG(exception));
- // no value was returned, return NULL
- return nullptr;
+ // no (additional) exception was thrown
+ return retval ? Value(retval) : nullptr;
}
/**