How can I return an strcut into PHP userspace from my extens

General discussion on PHP

How can I return an strcut into PHP userspace from my extens

Postby lian5364 on Wed Jan 31, 2018 3:31 am

i write a PHP extension,need return several value to php userspace, so i want to return a struct or a object to PHP ,

how can i achieve it? what should i do both PHP extension side and php userspace side?


my struct define:

typedef struct tagST_MUITI_FRAME_INFO
{
uint32 lAllDataSize;
uint16 unPacketNum;
uint16 unPacketIndex;
uint16 unPacketSize;
uint16 unRsv;
}ST_MUITI_FRAME_INFO;


typedef struct tagST_MESSAGE_INFO
{
int32 lMsgID; //
int32 lMsgLen; //
int8 cFrameType; //
int8 acRsv[31];
ST_MUITI_FRAME_INFO stMultiFrameInfo;
int8 acMsgBuff[0];

}ST_MESSAGE_INFO;



PHP_FUNCTION(GetMessageData)
{

char *pcSegData = NULL;
size_t lStrLen = 0;
size_t lSegDataLen = 0;
size_t lMessageInfoLen = 0;

zval *param;
zval *Message;
zval retval;

… …

lMessageInfoLen = sizeof(ST_MESSAGE_INFO) + lSegDataLen;

pstMessageInfo = (ST_MESSAGE_INFO*)malloc(lMessageInfoLen);

if (NULL == pstMessageInfo)
{
printf("malloc failed! in %s\n",__FUNCTION__);
goto end;
}


... ...

//i want to return pstMessageInfo to php

RETURN_ZVAL(&retval, 0, 1); // here i don't want to return a single value ,but want return a object or a struct

}




i found a similar topic here, may be it can provide some extra information
//________________________________________________________________________________________

How can I return an object into PHP userspace from my extension?

I have a C++ object, Graph, which contains a property named cat of type Category. I'm exposing the Graph object to PHP in an extension I'm writing in C++.

As long as the Graph's methods return primitives like boolean or long, I can use the Zend RETURN_*() macros (e.g. RETURN_TRUE(); or RETURN_LONG(123);. But how can I make


Graph->getCategory();

return a Category object for the PHP code to manipulate?

here's the Graph code I have so far:
Code: Select all
#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


and some one answer:

In your internal functions, you can only return zvals, not arbitrary C++ objects. In your case, you must encapsulate the Category object either in a resource or in an object (like you did for the Graph object). Either way, you cannot automatically use the C++ object's methods and properties. You must then provide functions or methods (again, like you did for the Graph object) that then should call the underlying native methods and convert their results into zvals.

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:

Code: Select all
struct category_object {
    zend_object std;
    Category *categ;
};

then:

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 */
}
lian5364
 
Posts: 2
Joined: Wed Jan 31, 2018 2:57 am

Re: How can I return an strcut into PHP userspace from my ex

Postby redd6292 on Wed Jan 31, 2018 12:37 pm

I have a C++ object, Graph, which contains a property named cat of type Category. I'm exposing the Graph object to PHP in an extension I'm writing in C++.

As long as the Graph's methods return primitives like boolean or long, I can use the Zend RETURN_*() macros (e.g. RETURN_TRUE(); or RETURN_LONG(123);. But how can I make


Graph->getCategory();

return a Category obje
redd6292
 
Posts: 1
Joined: Wed Jan 31, 2018 12:32 pm
Location: Dallas

Re: How can I return an strcut into PHP userspace from my ex

Postby lian5364 on Wed Jan 31, 2018 1:05 pm

redd6292 wrote:I have a C++ object, Graph, which contains a property named cat of type Category. I'm exposing the Graph object to PHP in an extension I'm writing in C++.

As long as the Graph's methods return primitives like boolean or long, I can use the Zend RETURN_*() macros (e.g. RETURN_TRUE(); or RETURN_LONG(123);. But how can I make


Graph->getCategory();

return a Category obje


sorry what are you answer meaning ?
lian5364
 
Posts: 2
Joined: Wed Jan 31, 2018 2:57 am


Return to PHP

Who is online

Users browsing this forum: No registered users and 1 guest