calling protected PHP_METHOD via call_user_function; missing context ??
| From: | Nathan Nobbe | Date: | Tue, 30 Dec 2008 20:11:26 +0000 |
| Subject: | calling protected PHP_METHOD via call_user_function; missing context ?? | ||
| Groups: | php.pecl.dev | ||
| Request: | Send a blank email to pecl-dev+get-6026@lists.php.net to get a copy of this message | ||
hi all,
im new to php extension writing; but ive been working through my first one,
which is completely object oriented, and ive hit a snag. normally, i can
just grep through the other extensions to find the answer, but ive been
unable to find anything similar.
heres the grep cmd, where the directory is ext in the php source
egrep -rn '^PHP_METHOD.*__construct\)$' ../
heres what im trying to replicate from userspace,
public function __construct()
{
$this->subCommands = array();
$this->initializeMacroCommand();
}
protected function initializeMacroCommand()
{
}
and heres what ive got in the extension
/* MacroCommand */
/* {{{ proto public void MacroCommand::__construct()
Constructor. */
PHP_METHOD(MacroCommand, __construct)
{
zval *this, retval, *callback;
zend_class_entry *this_ce;
ZVAL_STRING(&method, "initializeMacroCommand", 0);
this = getThis();
this_ce = zend_get_class_entry(this);
array_init(return_value);
/* create a callback so we have some context - still doesnt work =/ */
MAKE_STD_ZVAL(callback);
array_init(callback);
add_next_index_zval(callback, this);
zval_add_ref(&this);
add_next_index_string(callback, "initializeMacroCommand", 1);
zend_update_property(this_ce, this, "subCommands",
sizeof("subCommands")-1,
return_value TSRMLS_CC);
call_user_function(&this_ce->function_table, &this, callback, &retval,
0,
(zval**)NULL TSRMLS_CC);
zval_dtor(callback);
}
/* }}} */
/* {{{ proto protected void MacroCommand::initializeMacroCommand
this is a hook method to be overriden by subclasses, which will be called
by the constructor */
PHP_METHOD(MacroCommand, initializeMacroCommand)
{
}
...
static function_entry puremvc_macrocommand_class_methods[] = {
PHP_ME(MacroCommand, __construct, NULL, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC)
* PHP_ME(MacroCommand, initializeMacroCommand, NULL, ZEND_ACC_PROTECTED)*
{ NULL, NULL, NULL }
};
heres the phpt test
--TEST--
MacroCommand::execute(), ensure calls to each commands execute methods are
invokded
--SKIPIF--
<?php if (!extension_loaded("pure_mvc")) print "skip"; ?>
--FILE--
<?php
class SubCommand {
var $id = -1;
public function __construct($id) {
$this->id = $id;
}
public function execute() {
echo $id . PHP_EOL;
}
}
class MyNotification implements INotification {
public function getName() {}
public function getType() {}
public function getBody() {}
public function setName($name) {}
public function setBody($body) {}
public function setType($type) {}
public function toString() {}
}
$subCmd1 = new SubCommand(1);
$subCmd2 = new SubCommand(2);
$macroCmd = new MacroCommand(); // < FATAL HERE
/*
$macroCmd->addSubCommand($subCmd1);
$macroCmd->addSubCommand($subCmd2);
$macroCmd->execute(new MyNotification());
*/
echo '12';
?>
--EXPECT--
12
which is encountering a fatal error,
bash-3.2$ cat tests/testMacroCommandExecute.out
Fatal error: Call to protected method MacroCommand::initializeMacroCommand()
from context ''
if i change the declaration of iniitializeMacroCommand to be public, it
works.
PHP_ME(MacroCommand, initializeMacroCommand, NULL, ZEND_ACC_PUBLIC)
at first i was just passing a zval containing the string
initializeMacroCommand, but then i switched to an array containing the zval
from getThis() and another w/ the string initializeMacroCommand, but that
didnt seem to have any effect.
can someone steer me in the right direction, or give me some pointers on how
to determine what im doing wrong? sorry for the long winded post, btw, i
thought it best to be thorough.
tia,
-nathan