Как я могу вернуть объект в пользовательское пространство PHP из моего расширения?
У меня есть объект C++, Graph
, который содержит свойство с именем cat
типа Category
, Я разоблачаю Graph
объект в PHP в расширении я пишу в C++.
Пока Graph
методы возвращают примитивы типа boolean или long, я могу использовать Zend RETURN_*()
макросы (например, RETURN_TRUE();
или же RETURN_LONG(123);
, Но как я могу сделать
Graph->getCategory();
вернуть Category
объект для кода PHP, чтобы манипулировать?
Я следую инструкциям на http://devzone.zend.com/article/4486, и вот код Graph, который у меня есть:
#include "php_getgraph.h" zend_object_handlers graph_object_handlers; struct graph_object {zend_object std; График * График; }; zend_class_entry *graph_ce; #define PHP_CLASSNAME "WFGraph" ZEND_BEGIN_ARG_INFO_EX(php_graph_one_arg, 0, 0, 1) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(php_graph_two_args, объект 0, 0: 0_0_____)_объект_объекта_объекта (0)_объект_области; удалить объект-> график; zend_hash_destroy(obj->std.properties); FREE_HASHTABLE(obj->std.properties); efree(OBJ); } zend_object_value graph_create_handler(zend_class_entry *type TSRMLS_DC) { zval *tmp; zend_object_value retval; graph_object *obj = (graph_object*)emalloc(sizeof(graph_object)); memset(obj, 0, sizeof(graph_object)); obj->std.ce = type; ALLOC_HASHTABLE(obj->std.properties); zend_hash_init(obj->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0); zend_hash_copy(obj->std.properties, &type->default_properties, (copy_ctor_func_t)zval_add_ref, (void*)&tmp, sizeof(zval*)); retval.handle = zend_objects_store_put(obj, NULL, graph_free_storage, NULL TSRMLS_CC); retval.handlers = &graph_object_handlers; обратный возврат; } PHP_METHOD(Graph, __construct) { char * перспективы; int перспективный_лен; Graph *graph = NULL; zval *object = getThis(); if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", & перспективы, & перспективы s_len) == FAILURE) { RETURN_NULL(); } график = новый график (перспективы); graph_object *obj = (graph_object*)zend_object_store_get_object(объект TSRMLS_CC); obj->graph = graph; } PHP_METHOD(Graph, hasCategory) {длинная перспектива; График * График; graph_object *obj = (graph_object*)zend_object_store_get_object(getThis() TSRMLS_CC); graph = obj->graph; if (graph == NULL) { RETURN_NULL(); } if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", PerspectiveId) == FAILURE) { RETURN_NULL(); } RETURN_BOOL(graph->hasCategory(спективный идентификатор)); } PHP_METHOD(Graph, getCategory) { // что здесь делать? RETURN_TRUE; } Function_entry php_getgraph_functions[] = { PHP_ME(график, __ конструкция,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) PHP_ME(график,hasCategory,php_graph_one_arg,ZEND_ACC_PUBLIC) PHP_ME(график,getCategory,php_graph_one_arg,ZEND_ACC_PUBLIC) { NULL, NULL, NULL } }; PHP_MINIT_FUNCTION(getgraph) { zend_class_entry ce; INIT_CLASS_ENTRY(ce, PHP_CLASSNAME, php_getgraph_functions); graph_ce = zend_register_internal_class(&ce TSRMLS_CC); graph_ce->create_object = graph_create_handler; memcpy(&graph_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); graph_object_handlers.clone_obj = NULL; возврат УСПЕХА; } zend_module_entry getgraph_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif PHP_GETGRAPH_EXTNAME, NULL, /* функции */ PHP_MINIT(getgraph), NUTH * * NULL / * NULL / * NULL / * NULL / * NULL / * NULL / * NULL / * NULL / * NULL / * NULL / * NULL / * * NULL, /* MINFO */ #if ZEND_MODULE_API_NO >= 20010901 PHP_GETGRAPH_EXTVER, #endif STANDARD_MODULE_PROPERTIES }; #ifdef COMPILE_DL_GETGRAPH extern "C" { ZEND_GET_MODULE(getgraph) } #endif
1 ответ
Во внутренних функциях вы можете возвращать только zvals, но не произвольные объекты C++. В вашем случае вы должны инкапсулировать объект Category либо в ресурс, либо в объект (как вы это делали для объекта Graph). В любом случае, вы не можете автоматически использовать методы и свойства объекта C++. Затем вы должны предоставить функции или методы (опять же, как вы это сделали для объекта Graph), которые затем должны вызывать базовые нативные методы и преобразовывать их результаты в zvals.
edit: ОК, я предполагаю, что вы уже объявили класс Category как класс PHP, его таблица входа в класс находится в ce_category
и у вас есть этот тип:
struct category_object {
zend_object std;
Category *categ;
};
затем:
PHP_METHOD(Graph, getCategory)
{
graph_object *obj = (graph_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
struct category_object *co;
//You ought to check whether obj is NULL and maybe throw an exception or call zend_error...
if (object_init_ex(return_value, ce_category) != SUCCESS) {
//error handling
}
co = (struct category_object *) zend_object_store_get_object(return_value TSRMLS_CC);
assert (co != NULL); //should not happen; object was just created
co->categ = retrieve_category_from_graph(obj->graph);
/* IMPORTANT NOTE: if the Category object is held by the Graph object
* (that is, it is freed when the Graph object is freed), you should either:
* - Copy the Category object, so that it is independent.
* - Increment the refcount of the PHP Graph object with
* zend_objects_store_add_ref(_by_handle). In that case, you should also store the
* handle of the PHP Graph object so that you can decrease the refcount when the
* PHP Category object is destroyed. Alternatively, you can store an IS_OBJECT
* zval and indirectly manipulate the object refcount through construction/destruction
* of the zval */
}