Skip to content

(feature) Implementing a userland interface #528

@kakserpom

Description

@kakserpom

Problem

While waiting for #527 I tried this:

pub fn ce_my_userland_interface() -> &'static ClassEntry {
    ClassEntry::try_find("\\MyUserlandInterface").expect("\\MyUserlandInterface not found")
}

// ...

#[php(implements(ce = ce_my_userland_interface, stub = "\\MyUserlandInterface"))]

But then there doesn't seem to be an obvious way to run a script before loading the extension.
So the interface class is not defined at startup time and ce_my_userland_interface() panics.

Solution

pub fn adhoc_php_class_implements(class: &str, interface: &str) -> Option<()> {
    use ext_php_rs::ffi::zend_do_implement_interface;
    use ext_php_rs::types::ZendStr;
    use ext_php_rs::zend::ClassEntry;
    use ext_php_rs::zend::ExecutorGlobals;
    use std::ptr;
    ExecutorGlobals::get().class_table()?;
    let mut class = ZendStr::new(class, false);
    let interface = ClassEntry::try_find(interface)?;
    unsafe {
        zend_do_implement_interface(
            ext_php_rs::ffi::zend_lookup_class_ex(
                &raw mut *class,
                ptr::null_mut(),
                0,
            )
            .as_mut()?,
            ptr::from_ref(interface).cast_mut(),
        )
    };
    Some(())
}

Then in some place like __construct:

static INIT: Once = Once::new();
INIT.call_once(|| {
    adhoc_php_class_implements(
        "MyClass",
        "MyInterface",
    );
});

I think it would be useful to add this feature to ext-php-rs.

What do you guys think?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions