Nasıl benim uzantısı PHP userspace içine bir nesne dönebilirsiniz?

1 Cevap php

I cat türünde Category adında bir özellik içeren bir C + + nesne, Graph, var. Ben C + + yazıyorum bir uzantısı PHP Graph nesne maruz değilim.

Sürece Graph 's gibi yöntemler mantıksal ya da uzun gibi ilkel dönmek, ben Zend RETURN_*() makrolar (örneğin RETURN_TRUE(); kullanın veya {[(3)] olabilir }. Ama nasıl yapabilirsiniz

Graph->getCategory();

işlemek için PHP kodu için Category nesne döndürür?

I http://devzone.zend.com/article/4486 at üzerinde öğretici takip ediyorum, ve burada ben bugüne kadar Grafik kodu:

#include "php_getgraph.h"

zend_object_handlers graph_object_handlers;
struct graph_object {
 zend_object std;
 Graph *graph;
};

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, 2)
ZEND_END_ARG_INFO()


void graph_free_storage(void *object TSRMLS_DC) 
{
 graph_object *obj = (graph_object*)object;
 delete obj->graph;

 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;

 return retval;
}

PHP_METHOD(Graph, __construct)
{
 char *perspectives;
 int perspectives_len;
 Graph *graph = NULL;
 zval *object = getThis();

 if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &perspectives, &perspectives_len) == FAILURE) { 
  RETURN_NULL();
 }

 graph = new Graph(perspectives);
 graph_object *obj = (graph_object*)zend_object_store_get_object(object TSRMLS_CC);
 obj->graph = graph;
}
PHP_METHOD(Graph, hasCategory)
{
 long perspectiveId;

 Graph *graph;
 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(perspectiveId));
}
PHP_METHOD(Graph, getCategory)
{
 // what to do here?
 RETURN_TRUE;
}
function_entry php_getgraph_functions[] = {
 PHP_ME(Graph,__construct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)

 PHP_ME(Graph,hasCategory,php_graph_one_arg,ZEND_ACC_PUBLIC) 
 PHP_ME(Graph,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;
 return SUCCESS;
}

zend_module_entry getgraph_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
 STANDARD_MODULE_HEADER,
#endif
 PHP_GETGRAPH_EXTNAME,
 NULL,                   /* Functions */
 PHP_MINIT(getgraph),
 NULL,                   /* MSHUTDOWN */
 NULL,                   /* RINIT */
 NULL,                   /* RSHUTDOWN */
 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 Cevap

Iç fonksiyonları, sen sadece keyfi C + + nesneleri, zvals dönebilirsiniz. (Eğer Grafik nesnesi için yaptığımız gibi) durumunda, bir kaynak ya da bir nesnenin ya Kategori nesne saklanması gerekir. Her iki şekilde, otomatik olarak C + + nesnenin yöntemlerini ve özelliklerini kullanamazsınız. (Eğer Grafik nesne için yaptığı gibi, yine) siz daha sonra yatan yerli yöntemleri çağırır ve zvals onların sonuçları dönüştürmek gerektiğini işlevleri veya yöntemlerini sağlamanız gerekir.

edit: OK, I assume you've already declare the Category class as a PHP class, its class entry table is in ce_category and you have this type:

struct category_object {
    zend_object std;
    Category *categ;
};

sonra:

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 */
}