davidcole1340 / ext-php-rs

Bindings for the Zend API to build PHP extensions natively in Rust.
Apache License 2.0
584 stars 62 forks source link

Panic when using PhpException::from_class #117

Open joehoyle opened 2 years ago

joehoyle commented 2 years ago

When running the example from https://github.com/davidcole1340/ext-php-rs/blob/466c1658e3c91db3398c585a3b859b18e5b8e070/guide/src/macros/classes.md#example in returning an exception using PhpException::from_class::<RedisException>, I'm seeing a panic:

thread '<unnamed>' panicked at 'Attempted to access uninitalized class object', /Users/joe/.cargo/git/checkouts/ext-php-rs-0adfd3c26f55092c/f9528f0/src/types/class_object.rs:245:14
stack backtrace:
   0: rust_begin_unwind
             at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35/library/std/src/panicking.rs:517:5
   1: core::panicking::panic_fmt
             at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35/library/core/src/panicking.rs:101:14
   2: core::option::expect_failed
             at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35/library/core/src/option.rs:1615:5
   3: core::option::Option<T>::expect
             at /rustc/59eed8a2aac0230a8b53e89d4e99d55912ba6b35/library/core/src/option.rs:698:21
   4: <ext_php_rs::types::class_object::ZendClassObject<T> as core::ops::deref::DerefMut>::deref_mut
             at /Users/joe/.cargo/git/checkouts/ext-php-rs-0adfd3c26f55092c/f9528f0/src/types/class_object.rs:243:9
   5: ext_php_rs::zend::handlers::<impl ext_php_rs::ffi::_zend_object_handlers>::write_property::internal
             at /Users/joe/.cargo/git/checkouts/ext-php-rs-0adfd3c26f55092c/f9528f0/src/zend/handlers.rs:139:30
   6: ext_php_rs::zend::handlers::<impl ext_php_rs::ffi::_zend_object_handlers>::write_property
             at /Users/joe/.cargo/git/checkouts/ext-php-rs-0adfd3c26f55092c/f9528f0/src/zend/handlers.rs:153:15
   7: _zend_update_property_ex
   8: _zend_throw_exception_zstr
   9: _zend_throw_exception
  10: _zend_throw_exception_ex
  11: ext_php_rs::exception::throw_with_code
             at /Users/joe/.cargo/git/checkouts/ext-php-rs-0adfd3c26f55092c/f9528f0/src/exception.rs:138:9
  12: ext_php_rs::exception::PhpException::throw
             at /Users/joe/.cargo/git/checkouts/ext-php-rs-0adfd3c26f55092c/f9528f0/src/exception.rs:65:9
  13: <core::result::Result<T,E> as ext_php_rs::convert::IntoZval>::set_zval
             at /Users/joe/.cargo/git/checkouts/ext-php-rs-0adfd3c26f55092c/f9528f0/src/convert.rs:186:17
  14: php_v8::V8Js::_internal_php_execute_string
             at ./src/lib.rs:141:1
  15: _ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER
  16: _execute_ex
  17: _zend_execute
  18: _zend_eval_stringl
  19: _zend_eval_stringl_ex
  20: _do_cli
  21: _main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
fatal runtime error: failed to initiate panic, error 5
zsh: abort      RUST_BACKTRACE=1 php -r 
davidcole1340 commented 2 years ago

Seems there is more work to be done regarding extending PHP classes when having a Rust struct backing the new class. In the meantime for exceptions, can use the following example:

use ext_php_rs::{
    builders::ClassBuilder,
    exception::PhpResult,
    prelude::*,
    zend::{ce, ClassEntry},
};

static mut REDIS_EXCEPTION: Option<&'static ClassEntry> = None;

#[php_startup]
pub fn startup() {
    let ce = ClassBuilder::new("Redis\\Exception\\RedisException")
        .extends(ce::exception())
        .build()
        .expect("Failed to build RedisException");
    unsafe { REDIS_EXCEPTION.replace(ce) };
}

#[php_function]
pub fn get_redis_exc() -> PhpResult {
    Err(PhpException::new("noo!".into(), 0, unsafe {
        REDIS_EXCEPTION.expect("did not set exception ce")
    }))
}

#[php_module]
pub fn get_module(module: ModuleBuilder) -> ModuleBuilder {
    module
}
joehoyle commented 2 years ago

Ah, thanks so much for the workaround @davidcole1340 !