1

タイプGraphという名前のプロパティを含むC++ オブジェクト があります。C++ で作成している拡張機能でオブジェクトを PHP に公開しています。catCategoryGraph

Graphのメソッドが boolean や long などのプリミティブを返す限り、Zend マクロを使用できますRETURN_*()(たとえばRETURN_TRUE();、 またはRETURN_LONG(123);.しかし、どうすれば

Graph->getCategory();

CategoryPHP コードが操作するオブジェクトを返しますか?

http://devzone.zend.com/article/4486のチュートリアルに従っています。これまでに作成したグラフ コードは次のとおりです。

#include "php_getgraph.h"

zend_object_handlers graph_object_handlers;
struct グラフ_オブジェクト {
 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, 2)
ZEND_END_ARG_INFO()


void graph_free_storage(void *オブジェクト TSRMLS_DC)
{
 グラフ オブジェクト *obj = (グラフ オブジェクト*) オブジェクト;
 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 = タイプ;

 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;

 retval を返します。
}

PHP_METHOD(グラフ、__construct)
{
 char *パースペクティブ;
 int パースペクティブ_len;
 グラフ *graph = NULL;
 zval *object = getThis();

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

 グラフ = 新しいグラフ (パースペクティブ);
 グラフ オブジェクト *obj = (グラフ オブジェクト *)zend_object_store_get_object (オブジェクト TSRMLS_CC);
 obj->graph = グラフ;
}
PHP_METHOD(グラフ、hasCategory)
{
 長い視点Id;

 グラフ *グラフ;
 graph_object *obj = (graph_object*)zend_object_store_get_object(getThis() TSRMLS_CC);
 グラフ = obj->グラフ;

 もし (グラフ == NULL) {
  RETURN_NULL();
 }

 if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &perspectiveId) == FAILURE) {
  RETURN_NULL();
 }

 RETURN_BOOL(graph->hasCategory(perspectiveId));
}
PHP_METHOD(グラフ, getCategory)
{
 // ここで何をすべきか?
 RETURN_TRUE;
}
function_entry php_getgraph_functions[] = {
 PHP_ME(Graph,__construct,NULL,ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)

 PHP_ME(グラフ,hasCategory,php_graph_one_arg,ZEND_ACC_PUBLIC)
 PHP_ME(Graph,getCategory,php_graph_one_arg,ZEND_ACC_PUBLIC)
 {ヌル、ヌル、ヌル}
};

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)、
 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

4

1 に答える 1

3

内部関数では、任意の C++ オブジェクトではなく、zval のみを返すことができます。あなたの場合、 Category オブジェクトをリソースまたはオブジェクトにカプセル化する必要があります ( Graph オブジェクトの場合と同様)。いずれにしても、C++ オブジェクトのメソッドとプロパティを自動的に使用することはできません。次に、基になるネイティブ メソッドを呼び出して、その結果を zval に変換する関数またはメソッドを提供する必要があります (ここでも、Graph オブジェクトに対して行ったように)。

編集: わかりました。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 */
}
于 2010-05-12T20:31:45.637 に答える