title: How can I return an object into PHP userspace from my extension?
body: <p>I have a C++ object, <code>Graph</code>, which contains a property named <code>cat</code> of type <code>Category</code>. I'm exposing the <code>Graph</code> object to PHP in an extension I'm writing in C++. </p>
  
  <p>As long as the <code>Graph</code>'s methods return primitives like boolean or long, I can use the Zend <code>RETURN_*()</code> macros (e.g. <code>RETURN_TRUE();</code> or <code>RETURN_LONG(123);</code>. But how can I make </p>
  
  <p><code>
  Graph->getCategory();
  </code></p>
  
  <p>return a <code>Category</code> object for the PHP code to manipulate?</p>
  
  <p>I'm following the tutorial over at <a href="http://devzone.zend.com/article/4486" rel="nofollow noreferrer">http://devzone.zend.com/article/4486</a>, and here's the Graph code I have so far:</p>
  
  <pre>
  #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
  
  </pre>