Browse Source

blah

experimental/new_ui_api
Harald Radi 24 years ago
parent
commit
11a67831d1
  1. 97
      ext/rpc/RPC_HOWTO
  2. 110
      ext/rpc/com/com.c
  3. 63
      ext/rpc/handler.h
  4. 6
      ext/rpc/php_rpc.h
  5. 109
      ext/rpc/rpc.c
  6. 15
      ext/rpc/rpc.h
  7. 14
      ext/rpc/tests/test1.php

97
ext/rpc/RPC_HOWTO

@ -0,0 +1,97 @@
what's this ?
=============
This is an abstraction layer that eases the task of writing rpc
extensions (e.g. java, com, corba, soap, srm, .net, xml-rpc, ..).
it maps the quite complex ZendEngine2 oo api to a few simpler to
handle callback functions declared in the 'rpc_object_handlers'
struct.
so what happens behind my back ?
================================
- the abstraction layer takes care of your underlaying data structure
and passes it to you each time you have to handle an operation.
- it does reference counting and tells you when you have to destruct
your underlaying data structure.
- it registers a class and four functions (xxx_load, xxx_call, xxx_get,
xxx_set) for your rpc layer and checks if the parameters are valid (beside
the ones that are optional for your rpc layer).
- it silently creates proxies for references to members of your rpc
objects.
- it optionally does object pooling for objects that support it (has to
be defined in the constructor)
- it optionally requests hash values for method and property names and
caches them. call / get and set requests will then receive the hash value
instead of the original function- / propertyname.
how can i make use of it ?
==========================
take ext/rpc/com/com.c as a starting point. you'll have to set up the following struct:
typedef struct _rpc_object_handlers {
int (*rpc_hash)(char *name, zend_uint name_len, char **hash, zend_uint *hash_len, int type);
int hash_type;
int (*rpc_ctor)(char *class_name, zend_uint class_name_len, void **data, INTERNAL_FUNCTION_PARAMETERS);
int (*rpc_dtor)(void **data);
int (*rpc_call)(char *method_name, zend_uint method_name_len, void **data, INTERNAL_FUNCTION_PARAMETERS);
int (*rpc_get)(char *property_name, zend_uint property_name_len, zval *return_value, void **data);
int (*rpc_set)(char *property_name, zend_uint property_name_len, zval *value, zval *return_value, void **data);
int (*rpc_compare)(void **data1, void **data2);
int (*rpc_get_classname)(char **class_name, zend_uint *class_name_length, void **data);
int (*rpc_has_property)(char *property_name, zend_uint property_name_length, void **data);
int (*rpc_unset_property)(char *property_name, zend_uint property_name_length, void **data);
int (*rpc_get_properties)(HashTable **properties, void **data);
} rpc_object_handlers;
rpc_hash:
the hashing function for method and property names. returns a hash value
for the string passed in 'name'. 'type' is either METHOD or PROPERTY.
if you set 'hash_type' to HASH_AS_INT you can set '*hash' to NULL and pass
the hash value as 'hash_len'.
rpc_hash can be set to NULL if hashing of method and property names is not
appreciated.
hash_type:
either HASH_AS_INT, HASH_AS_STRING or DONT_HASH
rpc_ctor:
the constructor
rpc_dtor:
the destructor
rpc_call:
the call handler
rpc_get:
the get handler
rpc_set:
the set handler
rpc_compare:
the compare handler.
rpc_compare can be set to NULL then objects will be treated the same if they
belong to the same rpc layer.
rpc_get_classname:
returns the classname.
rpc_get_classname can be set to NULL then the name of the rpc layer will be
used as classname.
rpc_has_property:
check if a property exists.
rpc_has_property can be set to NULL then true will be returned for every request.
rpc_unset_property:
unset a property.
rpc_unset_property can be set to NULL, a 'not supported' warning will then be
issued.
rpc_get_properties:
returns a HashTable with all the properties.
rpc_get_properties can be set to NULL, then a list of the explicit declared
properties will be returned.

110
ext/rpc/com/com.c

@ -1,11 +1,111 @@
#include <stdio.h>
#include "../handler.h"
#include "../php_rpc.h"
#include "com.h"
RPC_REGISTER_HANDLERS(com)
/* protos */
static int com_hash(char *name, zend_uint name_len, char **hash, zend_uint *hash_len, int type);
static int com_ctor(char *class_name, zend_uint class_name_len, void **data, INTERNAL_FUNCTION_PARAMETERS);
static int com_dtor(void **data);
static int com_call(char *method_name, zend_uint method_name_len, void **data, INTERNAL_FUNCTION_PARAMETERS);
static int com_get(char *property_name, zend_uint property_name_len, zval *return_value, void **data);
static int com_set(char *property_name, zend_uint property_name_len, zval *value, zval *return_value, void **data);
static int com_compare(void **data1, void **data2);
static int com_get_classname(char **class_name, zend_uint *class_name_length, void **data);
static int com_has_property(char *property_name, zend_uint property_name_length, void **data);
static int com_unset_property(char *property_name, zend_uint property_name_length, void **data);
static int com_get_properties(HashTable **properties, void **data);
/* register rpc callback function */
RPC_REGISTER_HANDLERS_START(com, DONT_POOL)
com_hash,
HASH_AS_STRING,
com_ctor,
com_dtor,
com_call,
com_get,
com_set,
com_compare,
com_get_classname,
com_has_property,
com_unset_property,
com_get_properties
RPC_REGISTER_HANDLERS_END()
/* register userspace functions */
RPC_FUNCTION_ENTRY_START(com)
ZEND_FALIAS(com_invoke, rpc_call, NULL)
ZEND_FE(com_addref, NULL)
RPC_FUNCTION_ENTRY_END()
RPC_INIT_FUNCTION(com) {
/* register class methods */
RPC_METHOD_ENTRY_START(com)
ZEND_FALIAS(addref, com_addref, NULL)
RPC_METHOD_ENTRY_END()
/* init function that is called before the class is registered
* so you can do any tricky stuff in here
*/
RPC_INIT_FUNCTION(com)
{
}
/* rpc handler functions */
static int com_hash(char *name, zend_uint name_len, char **hash, zend_uint *hash_len, int type)
{
return SUCCESS;
}
static int com_ctor(char *class_name, zend_uint class_name_len, void **data, INTERNAL_FUNCTION_PARAMETERS)
{
return SUCCESS;
}
static int com_dtor(void **data)
{
return SUCCESS;
}
static int com_call(char *method_name, zend_uint method_name_len, void **data, INTERNAL_FUNCTION_PARAMETERS)
{
return SUCCESS;
}
static int com_get(char *property_name, zend_uint property_name_len, zval *return_value, void **data)
{
return SUCCESS;
}
static int com_set(char *property_name, zend_uint property_name_len, zval *value, zval *return_value, void **data)
{
return SUCCESS;
}
static int com_compare(void **data1, void **data2)
{
return SUCCESS;
}
static int com_get_classname(char **class_name, zend_uint *class_name_length, void **data)
{
return SUCCESS;
}
static int com_has_property(char *property_name, zend_uint property_name_length, void **data)
{
return SUCCESS;
}
static int com_unset_property(char *property_name, zend_uint property_name_length, void **data)
{
return SUCCESS;
}
static int com_get_properties(HashTable **properties, void **data)
{
return SUCCESS;
}
/* custom functions */
ZEND_FUNCTION(com_addref)
{
}

63
ext/rpc/handler.h

@ -3,46 +3,87 @@
#include "php.h"
#define RPC_HANDLER(layer) {#layer, layer##_handler_init, &layer##_object_handlers, &layer##_class_entry, layer##_function_entry}
#define RPC_HANDLER(layer) {#layer, layer##_handler_init, &layer##_object_handlers, \
&layer##_class_entry, layer##_function_entry, \
layer##_method_entry, &layer##_pool}
#define RPC_DECLARE_HANDLER(layer) void layer##_handler_init(); \
const int layer##_pool; \
rpc_object_handlers layer##_object_handlers; \
zend_class_entry layer##_class_entry; \
function_entry layer##_function_entry[];
function_entry layer##_function_entry[]; \
function_entry layer##_method_entry[];
#define RPC_INIT_FUNCTION(layer) void layer##_handler_init()
#define RPC_REGISTER_HANDLERS(layer) zend_class_entry layer##_class_entry; \
rpc_object_handlers layer##_object_handlers; \
#define RPC_REGISTER_HANDLERS_START(layer, p) zend_class_entry layer##_class_entry; \
const int layer##_pool = p; \
rpc_object_handlers layer##_object_handlers = {
#define RPC_REGISTER_HANDLERS_END() };
#define RPC_FUNCTION_ENTRY_START(layer) function_entry layer##_function_entry[] = { \
PHP_FALIAS(layer##_load, rpc_load, NULL) \
PHP_FALIAS(layer##_call, rpc_call, NULL) \
PHP_FALIAS(layer##_get, rpc_get, NULL) \
PHP_FALIAS(layer##_set, rpc_set, NULL)
ZEND_FALIAS(layer##_load, rpc_load, NULL) \
ZEND_FALIAS(layer##_call, rpc_call, NULL) \
ZEND_FALIAS(layer##_get, rpc_get, NULL) \
ZEND_FALIAS(layer##_set, rpc_set, NULL)
#define RPC_FUNCTION_ENTRY_END() {NULL, NULL, NULL} \
};
#define RPC_METHOD_ENTRY_START(layer) function_entry layer##_method_entry[] = {
#define RPC_METHOD_ENTRY_END() {NULL, NULL, NULL} \
};
#define POOL TRUE
#define DONT_POOL FALSE
#define HASH_AS_INT TRUE
#define HASH_AS_STRING FALSE
#define DONT_HASH FALSE
#define METHOD 0
#define PROPERTY 1
/* rpc handler that have to be implemented by a
* specific rpc layer
*/
typedef struct _rpc_object_handlers {
int i;
int (*rpc_hash)(char *name, zend_uint name_len, char **hash, zend_uint *hash_len, int type);
int hash_type;
int (*rpc_ctor)(char *class_name, zend_uint class_name_len, void **data, INTERNAL_FUNCTION_PARAMETERS);
int (*rpc_dtor)(void **data);
int (*rpc_call)(char *method_name, zend_uint method_name_len, void **data, INTERNAL_FUNCTION_PARAMETERS);
int (*rpc_get)(char *property_name, zend_uint property_name_len, zval *return_value, void **data);
int (*rpc_set)(char *property_name, zend_uint property_name_len, zval *value, zval *return_value, void **data);
int (*rpc_compare)(void **data1, void **data2);
int (*rpc_get_classname)(char **class_name, zend_uint *class_name_length, void **data);
int (*rpc_has_property)(char *property_name, zend_uint property_name_length, void **data);
int (*rpc_unset_property)(char *property_name, zend_uint property_name_length, void **data);
int (*rpc_get_properties)(HashTable **properties, void **data);
} rpc_object_handlers;
/* handler entry */
typedef struct _rpc_handler_entry {
char *name;
void (*rpc_handler_init)();
rpc_object_handlers *handlers;
zend_class_entry *ce;
function_entry *functions;
function_entry *methods;
const int *pool_instances;
} rpc_handler_entry;
/* internal data */
typedef struct _rpc_internal {
zend_class_entry *ce;
rpc_object_handlers **handlers;
void *data;
int refcount;
void **data;
unsigned refcount;
unsigned clonecount;
int pool_instances;
} rpc_internal;
#endif /* HANDLER_H */

6
ext/rpc/php_rpc.h

@ -16,9 +16,9 @@ extern zend_module_entry rpc_module_entry;
#include "TSRM.h"
#endif
PHP_MINIT_FUNCTION(rpc);
PHP_MSHUTDOWN_FUNCTION(rpc);
PHP_MINFO_FUNCTION(rpc);
ZEND_MINIT_FUNCTION(rpc);
ZEND_MSHUTDOWN_FUNCTION(rpc);
ZEND_MINFO_FUNCTION(rpc);
ZEND_FUNCTION(rpc_load);
ZEND_FUNCTION(rpc_call);

109
ext/rpc/rpc.c

@ -27,7 +27,6 @@ static zend_object_value rpc_clone(zval *object TSRMLS_DC);
static zval* rpc_read(zval *object, zval *member, int type TSRMLS_DC);
static void rpc_write(zval *object, zval *member, zval *value TSRMLS_DC);
static zval** rpc_get_property(zval *object, zval *member TSRMLS_DC);
static zval** rpc_get_property_zval(zval *object, zval *member TSRMLS_DC);
static zval* rpc_get(zval *property TSRMLS_DC);
static void rpc_set(zval **property, zval *value TSRMLS_DC);
static int rpc_has_property(zval *object, zval *member, int check_empty TSRMLS_DC);
@ -48,7 +47,7 @@ static zend_object_handlers rpc_handlers = {
rpc_read,
rpc_write,
rpc_get_property,
rpc_get_property_zval,
NULL,
rpc_get,
rpc_set,
rpc_has_property,
@ -74,11 +73,11 @@ zend_module_entry rpc_module_entry = {
STANDARD_MODULE_HEADER,
"rpc",
rpc_functions,
PHP_MINIT(rpc),
PHP_MSHUTDOWN(rpc),
ZEND_MINIT(rpc),
ZEND_MSHUTDOWN(rpc),
NULL,
NULL,
PHP_MINFO(rpc),
ZEND_MINFO(rpc),
"0.1a",
STANDARD_MODULE_PROPERTIES
};
@ -120,7 +119,7 @@ static int rpc_global_startup(void)
/* create a class entry for every rpc handler */
INIT_OVERLOADED_CLASS_ENTRY((*(HANDLER.ce)),
HANDLER.name,
NULL,
HANDLER.methods,
NULL,
NULL,
NULL);
@ -149,9 +148,9 @@ static void rpc_globals_ctor(zend_rpc_globals *rpc_globals TSRMLS_DC)
{
}
/* {{{ PHP_MINIT_FUNCTION
/* {{{ ZEND_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(rpc)
ZEND_MINIT_FUNCTION(rpc)
{
/* GINIT */
if (thread_count++ == 0) {
@ -171,9 +170,9 @@ PHP_MINIT_FUNCTION(rpc)
}
/* }}} */
/* {{{ PHP_MSHUTDOWN_FUNCTION
/* {{{ ZEND_MSHUTDOWN_FUNCTION
*/
PHP_MSHUTDOWN_FUNCTION(rpc)
ZEND_MSHUTDOWN_FUNCTION(rpc)
{
/* GSHUTDOWN */
if (--thread_count == 0) {
@ -185,9 +184,9 @@ PHP_MSHUTDOWN_FUNCTION(rpc)
}
/* }}} */
/* {{{ PHP_MINFO_FUNCTION
/* {{{ ZEND_MINFO_FUNCTION
*/
PHP_MINFO_FUNCTION(rpc)
ZEND_MINFO_FUNCTION(rpc)
{
php_info_print_table_start();
php_info_print_table_header(2, "rpc support", "enabled");
@ -203,7 +202,9 @@ static void rpc_instance_dtor(void *pDest)
intern = (rpc_internal **) pDest;
/* TODO: destruct intern */
/* TODO: destruct custom data */
pefree(*intern, TRUE);
}
static zend_object_value rpc_create_object(zend_class_entry *class_type TSRMLS_DC)
@ -218,7 +219,8 @@ static zend_object_value rpc_create_object(zend_class_entry *class_type TSRMLS_D
/* set up the internal representation of our rpc instance */
intern = (rpc_internal *) pemalloc(sizeof(rpc_internal), TRUE);
intern->ce = class_type;
intern->refcount = 0;
intern->refcount = 1;
intern->clonecount = 1;
intern->data = NULL;
if (zend_hash_find(handlers, class_type->name, class_type->name_length + 1, (void **) &(intern->handlers)) == FAILURE) {
/* TODO: exception */
@ -247,29 +249,48 @@ static void rpc_add_ref(zval *object TSRMLS_DC)
static void rpc_del_ref(zval *object TSRMLS_DC)
{
GET_INTERNAL(intern);
rpc_internal **intern;
if (RPC_REFCOUNT(intern) > 0) {
RPC_DELREF(intern);
}
if (GET_INTERNAL_EX(intern, object) == SUCCESS) {
if (RPC_REFCOUNT(intern) > 0) {
RPC_DELREF(intern);
}
if (RPC_REFCOUNT(intern) == 0) {
rpc_instance_dtor(intern);
if (RPC_REFCOUNT(intern) == 0) {
zend_hash_index_del(instance, Z_OBJ_HANDLE(*object));
}
}
}
static void rpc_delete(zval *object TSRMLS_DC)
{
GET_INTERNAL(intern);
rpc_instance_dtor(intern);
rpc_internal **intern;
if (GET_INTERNAL_EX(intern, object) == SUCCESS) {
if (RPC_CLONECOUNT(intern) > 0) {
RPC_DELCLONE(intern);
}
if (RPC_CLONECOUNT(intern) == 0) {
zend_hash_index_del(instance, Z_OBJ_HANDLE_P(object));
}
}
}
static zend_object_value rpc_clone(zval *object TSRMLS_DC)
{
// TSRMLS_FETCH();
// GET_INTERNAL(intern);
GET_INTERNAL(intern);
/* cloning the underlaying resource is neither possible nor would it
* make sense, therfore we return the old zend_object_value and increase
* the clone count to not loose the clone when the original object gets
* deleted.
*/
RPC_ADDCLONE(intern);
/* also increase the refcounter as a clone is just another reference */
RPC_ADDREF(intern);
/* FIXME */
return object->value.obj;
}
@ -289,14 +310,8 @@ static void rpc_write(zval *object, zval *member, zval *value TSRMLS_DC)
static zval** rpc_get_property(zval *object, zval *member TSRMLS_DC)
{
// GET_INTERNAL(intern);
/* FIXME */
return NULL;
}
/* no idea how to return an object - wait for andi */
static zval** rpc_get_property_zval(zval *object, zval *member TSRMLS_DC)
{
// GET_INTERNAL(intern);
/* FIXME */
@ -342,16 +357,16 @@ static HashTable* rpc_get_properties(zval *object TSRMLS_DC)
static union _zend_function* rpc_get_method(zval *object, char *method, int method_len TSRMLS_DC)
{
zend_function *function;
GET_INTERNAL(intern);
function = (zend_function *) emalloc(sizeof(zend_function));
function->type = ZEND_OVERLOADED_FUNCTION;
function->common.arg_types = NULL;
function->common.function_name = method;
function->common.scope = NULL;
// GET_INTERNAL(intern);
if (zend_hash_find(&((*intern)->ce->function_table), method, method_len + 1, &function) == FAILURE) {
function = (zend_function *) emalloc(sizeof(zend_function));
function->type = ZEND_OVERLOADED_FUNCTION;
function->common.arg_types = NULL;
function->common.function_name = method;
function->common.scope = NULL;
}
/* FIXME */
return function;
}
@ -412,7 +427,7 @@ ZEND_FUNCTION(rpc_load)
/* the name of the rpc layer is prepended to '_load' so lets strip everything after
* the first '_' away from the function name
*/
zend_class_entry *ce;
zend_class_entry **ce;
key = estrdup(get_active_function_name(TSRMLS_C));
key_len = strchr(key, '_') - key;
key[key_len] = '\0';
@ -420,7 +435,6 @@ ZEND_FUNCTION(rpc_load)
/* get the class entry for the requested rpc layer */
if (zend_hash_find(CG(class_table), key, key_len + 1, (void **) &ce) == FAILURE) {
/* TODO: exception here */
RETURN_FALSE;
}
/* set up a new zval container */
@ -428,18 +442,21 @@ ZEND_FUNCTION(rpc_load)
INIT_PZVAL(object);
Z_TYPE_P(object) = IS_OBJECT;
ZVAL_REFCOUNT(object) = 1;
PZVAL_IS_REF(object) = 1;
/* create a new object */
object->value.obj = rpc_create_object(ce TSRMLS_CC);
object->value.obj = rpc_create_object(*ce TSRMLS_CC);
/* return the newly created object */
return_value = object;
/* now everything is set up the same way as if we were called as a constructor */
}
GET_INTERNAL_EX(intern, object);
if (GET_INTERNAL_EX(intern, object) == FAILURE) {
/* TODO: exception */
}
// (*intern)->handlers.rpc_ctor(
/* FIXME */
}

15
ext/rpc/rpc.h

@ -5,16 +5,21 @@
#define HANDLER handler_entries[__handler_counter]
#define HANDLER_COUNT (sizeof(handler_entries) / sizeof(rpc_handler_entry))
#define GET_INTERNAL(intern) rpc_internal **intern; \
GET_INTERNAL_EX(intern, object)
#define GET_INTERNAL_EX(intern, object) if (zend_hash_index_find(instance, object->value.obj.handle, (void **) &intern) == FAILURE) { \
/* TODO: exception */ \
}
#define GET_INTERNAL(intern) rpc_internal **intern; \
if (GET_INTERNAL_EX(intern, object) == FAILURE) { \
/* TODO: exception */ \
}
#define GET_INTERNAL_EX(intern, object) zend_hash_index_find(instance, object->value.obj.handle, (void **) &intern)
#define RPC_REFCOUNT(intern) ((*intern)->refcount)
#define RPC_ADDREF(intern) (++RPC_REFCOUNT(intern))
#define RPC_DELREF(intern) (--RPC_REFCOUNT(intern))
#define RPC_CLONECOUNT(intern) ((*intern)->clonecount)
#define RPC_ADDCLONE(intern) (++RPC_CLONECOUNT(intern))
#define RPC_DELCLONE(intern) (--RPC_CLONECOUNT(intern))
static int __handler_counter;
#endif

14
ext/rpc/tests/test1.php

@ -3,9 +3,19 @@ print "huhuhdsa";
$rpc = new com();
$rpc->call();
$rpc->addref();
$clone = $rpc->__clone();
//$rpc->prop = 1;
//$a = $rpc->prop;
$a = &$rpc->prop;
delete $rpc;
delete $clone;
$heh = com_load();
$heh->call;
delete $heh;
/*$heh->call;
delete $heh;*/
?>
Loading…
Cancel
Save