-
Notifications
You must be signed in to change notification settings - Fork 337
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Segmentation Fault When Trying To Fetch Built-In PHP Classes #276
Comments
It looks like the initialization of the extension takes place right after it is loaded. However, creation of all classes by the PHP Core happens during Module Init phase. http://lxr.php.net/xref/PHP-7.0/main/main.c#2216 - this is where PHP loads all extensions But the crash itself happens for a different reason: zend_fetch_class() looks up the class name in
Thus the proper way to fetch an internal class would be like this: #include <iostream>
#include <phpcpp.h>
#include <Zend/zend.h>
#include <Zend/zend_execute.h>
extern "C"
{
PHPCPP_EXPORT void *get_module()
{
// create extension
static Php::Extension extension("simple","1.0");
extension.onStartup([]() {
zend_string *name = zend_string_init(ZEND_STRL("DateTime"), 1);
zend_string *lc_name = zend_string_tolower(name);
zend_class_entry *dateTimeCE = static_cast<zend_class_entry*>(zend_hash_find_ptr(CG(class_table), lc_name));
zend_string_release(lc_name);
// if dateTimeCE is nullptr here, the class does not exist
std::cerr << dateTimeCE << std::endl;
});
return extension.module();
}
} However, as this is the very first time I am looking at the PHP-CPP code, I cannot suggest you yet how to register a class from |
Well, good news is that I have found the way to inherit from an internal class. Bad news is that you still cannot inherit from DateTime. So, this is how you do that: #include <cassert>
#include <phpcpp.h>
#include <Zend/zend.h>
#include <Zend/zend_execute.h>
#include <Zend/zend_API.h>
#include <Zend/zend_inheritance.h>
class MyClass : public Php::Base {
public:
virtual Php::Value method()
{
return 42;
}
};
extern "C"
{
PHPCPP_EXPORT void *get_module()
{
static Php::Extension extension("simple","1.0");
Php::Class<MyClass> myClass("MyClass");
myClass.method<&MyClass::method>("method");
extension.add(myClass);
extension.onStartup([]() {
zend_string *name = zend_string_init(ZEND_STRL("LibXMLError"), 1);
zend_string *lc_name = zend_string_tolower(name);
zend_class_entry *base_ce = static_cast<zend_class_entry*>(zend_hash_find_ptr(CG(class_table), lc_name));
zend_string_release(lc_name);
assert(base_ce != nullptr);
name = zend_string_init(ZEND_STRL("MyClass"), 1);
lc_name = zend_string_tolower(name);
zend_class_entry* myclass_ce = static_cast<zend_class_entry*>(zend_hash_find_ptr(CG(class_table), lc_name));
zend_string_release(lc_name);
assert(myclass_ce != nullptr);
zend_do_inheritance(myclass_ce, base_ce);
});
return extension.module();
}
} Now why you cannot inherit from DateTime: static void do_inherit_parent_constructor(zend_class_entry *ce) /* {{{ */
{
ZEND_ASSERT(ce->parent != NULL);
/* You cannot change create_object */
ce->create_object = ce->parent->create_object; that
INIT_CLASS_ENTRY(ce_date, "DateTime", date_funcs_date);
ce_date.create_object = date_object_new_date; And it appears that you can have only one So, zend_class_entry* myclass_ce = static_cast<zend_class_entry*>(zend_hash_find_ptr(CG(class_table), lc_name));
zend_string_release(lc_name);
assert(myclass_ce != nullptr);
if (!base_ce->create_object || base_ce->create_object == myclass_ce->create_object) {
zend_do_inheritance(myclass_ce, base_ce);
}
else {
// FAIL, you cannot inherit from the base class
} |
Hi
I'm trying to add generalised support for allowing a class to extend a built-in PHP class (Such as
\Exception
or\DateTime
, but when I try to fetch thezend_class_entry
with the followingI get a segmentation fault, with gdb giving the following backtrace
Using the
zend_fetch_class
method does work for classes that I define myself, as I'm later doing the following with no issueI can also get the default exception class with
zend_exception_get_default(TSRMLS_C)
, and register a class as extending from that, so I know that at the very least that's already registered. So my question is why does it segfault when I'm trying to fetch a built-in class, and how can I fetch it without Segfaults?The text was updated successfully, but these errors were encountered: