lua callbacks are now object bound
[phplua.git] / lua.c
blobc7b0f5e7ad8791652ea184f091d5a83d456cb0ac
1 /*
2 +----------------------------------------------------------------------+
3 | LUA extension for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2007 Johannes Schlueter |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Author: Johannes Schlueter <johannes@php.net> |
16 | Marcelo Araujo <msaraujo@php.net> |
17 | Andreas Streichardt <andreas.streichardt@globalpark.com |
18 +----------------------------------------------------------------------+
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
25 #include "php.h"
26 #include "php_ini.h"
27 #include "ext/standard/info.h"
28 #include "php_lua.h"
30 #include "lua.h"
31 #include "lauxlib.h"
32 #include "lualib.h"
34 #define EXT_LUA_VERSION PHP_LUA_VERSION
36 #ifdef LUA_STACK_DEBUG
37 #define LUA_STACK_START(L) int __lua_old_top = lua_gettop(L)
38 #define LUA_STACK_END(L) \
39 if (__lua_old_top != lua_gettop(L)) { \
40 php_error_docref(NULL TSRMLS_CC, E_WARNING, "wrong stack size (%i before operation, %i now)", __lua_old_top, lua_gettop(L)); \
42 #else
43 #define LUA_STACK_START(L)
44 #define LUA_STACK_END(L)
45 #endif
47 #define LUA_POP_ZVAL(L, z) \
48 php_lua_get_zval_from_stack(L, -1, z); \
49 lua_pop(L, 1)
51 ZEND_DECLARE_MODULE_GLOBALS(lua)
53 #define getLuaZ(var) (((php_lua_object*)zend_object_store_get_object(var TSRMLS_CC))->L)
54 #define getLuaY() ((php_lua_object*)zend_object_store_get_object(getThis() TSRMLS_CC))
55 #define getLua() getLuaZ(getThis())
57 static zend_object_handlers lua_handlers;
58 static zend_class_entry *lua_ce;
60 typedef struct _php_lua_object {
61 zend_object std;
62 lua_State *L;
63 zval **callbacks;
64 long callback_count;
65 } php_lua_object;
67 static const luaL_Reg php_lualibs[] = {
68 {"base", luaopen_base},
69 {LUA_LOADLIBNAME, luaopen_package},
70 {LUA_TABLIBNAME, luaopen_table},
71 {LUA_IOLIBNAME, luaopen_io},
72 {LUA_OSLIBNAME, luaopen_os},
73 {LUA_STRLIBNAME, luaopen_string},
74 {LUA_MATHLIBNAME, luaopen_math},
75 {LUA_DBLIBNAME, luaopen_debug},
76 {NULL, NULL}
79 static void php_lua_push_zval(lua_State *L, zval *val_p TSRMLS_DC);
80 static void php_lua_write_real_property(lua_State *L,int index,zval *prop, zval *value TSRMLS_DC);
82 static void *php_lua_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { /* {{{ */
83 if (nsize == 0) {
84 if (ptr) {
85 efree(ptr);
87 return NULL;
88 } else {
89 if (ptr) {
90 return erealloc(ptr, nsize);
91 } else {
92 return emalloc(nsize);
95 } /* }}} */
98 static void php_lua_push_array(lua_State *L, zval *array TSRMLS_DC) /* {{{ */
100 zval **data;
101 HashTable *arr_hash;
102 HashPosition pointer;
103 int array_count;
104 char *key;
105 int key_len;
106 long index;
107 int hash_key;
108 char *key_copy;
110 zval *zkey;
112 arr_hash = Z_ARRVAL_P(array);
113 array_count = zend_hash_num_elements(arr_hash);
115 lua_newtable(L);
117 for(zend_hash_internal_pointer_reset_ex(arr_hash, &pointer); zend_hash_get_current_data_ex(arr_hash, (void**) &data, &pointer) == SUCCESS; zend_hash_move_forward_ex(arr_hash, &pointer))
119 hash_key=zend_hash_get_current_key_ex(arr_hash, &key, &key_len, &index, 0, &pointer);
121 if (hash_key == HASH_KEY_IS_LONG && index == 0) {
122 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Trying to push array index %d to lua which is unsupported in lua. Element has been discarded",index);
124 else {
125 ALLOC_INIT_ZVAL(zkey);
126 if (hash_key == HASH_KEY_IS_STRING) {
127 key_copy=estrndup(key,key_len-1);
128 Z_TYPE_P(zkey)=IS_STRING;
129 Z_STRVAL_P(zkey)=key_copy;
130 Z_STRLEN_P(zkey)=key_len-1;
132 else {
133 Z_TYPE_P(zkey)=IS_LONG;
134 Z_LVAL_P(zkey)=index;
137 php_lua_write_real_property(L,-3,zkey,*data TSRMLS_CC);
138 zval_ptr_dtor(&zkey);
141 } /* }}} */
146 static void php_lua_push_zval(lua_State *L, zval *val_p TSRMLS_DC) /* {{{ */
148 /* TODO: Use proper type for lua and separate only when needed */
150 /* push into lua stack properly */
151 switch (Z_TYPE_P(val_p)) {
152 case IS_STRING:
153 lua_pushlstring(L, Z_STRVAL_P(val_p), Z_STRLEN_P(val_p));
154 break;
156 case IS_NULL:
157 lua_pushnil(L);
158 break;
160 case IS_DOUBLE:
161 lua_pushnumber(L, Z_DVAL_P(val_p));
162 break;
164 case IS_LONG:
165 lua_pushnumber(L, Z_LVAL_P(val_p));
166 break;
168 case IS_BOOL:
169 lua_pushboolean(L, Z_BVAL_P(val_p));
170 break;
172 case IS_ARRAY:
173 php_lua_push_array(L,val_p TSRMLS_CC);
174 break;
176 default:
177 php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid type `%s' supported in lua", zend_zval_type_name(val_p));
178 lua_pushnil(L);
179 break;
182 } /* }}} */
184 static int php_lua_push_apply_func(void *pDest, void *argument TSRMLS_DC) /* {{{ */
186 php_lua_push_zval((lua_State*)argument, *(zval**)pDest TSRMLS_CC);
187 return ZEND_HASH_APPLY_KEEP;
188 } /* }}} */
190 static void php_lua_get_zval_from_stack(lua_State *L, int index, zval *ret TSRMLS_DC) /* {{{ */
192 const char *value;
193 size_t value_len;
195 switch (lua_type(L, index)) {
196 case LUA_TBOOLEAN:
197 ZVAL_BOOL(ret, lua_toboolean(L, index));
198 break;
200 case LUA_TNUMBER:
201 ZVAL_DOUBLE(ret, lua_tonumber(L, index));
202 break;
204 case LUA_TSTRING:
205 value = lua_tolstring(L, index, &value_len);
206 ZVAL_STRINGL(ret, (char*)value, value_len, 1);
207 break;
209 case LUA_TTABLE:
210 array_init(ret);
211 /* notify lua to traverse the table */
212 lua_pushnil(L);
214 zval *akey,*aval;
216 /* table has been moved by one because of the pushnil */
217 /* this will ONLY work with negative indices! */
218 while (lua_next(L, index-1) != 0)
220 ALLOC_INIT_ZVAL(akey);
221 ALLOC_INIT_ZVAL(aval);
223 /* `key' is at index -2 and `value' at index -1 */
224 php_lua_get_zval_from_stack(L,-2,akey);
225 php_lua_get_zval_from_stack(L,-1,aval);
227 switch(Z_TYPE_P(akey))
229 /* lua can't use (at least when i tried ;) ) floats as array keys so that should be safe */
230 case IS_DOUBLE:
231 add_index_zval(ret,(long)Z_DVAL_P(akey),aval);
232 break;
233 default:
234 add_assoc_zval(ret,Z_STRVAL_P(akey),aval);
235 break;
237 lua_pop(L, 1); /* removes `value'; keeps `key' for next iteration */
238 zval_ptr_dtor(&akey);
240 break;
243 case LUA_TFUNCTION:
244 /* TODO: Make this a PHP Function */
246 default:
247 php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid type `%i' passed from lua.", lua_type(L, index));
248 /* fall-through */
250 case LUA_TNIL:
251 ZVAL_NULL(ret);
252 break;
255 } /* }}} */
257 static int php_lua_print(lua_State *L) /* {{{ */
259 int i;
260 int n = lua_gettop(L);
262 for (i = 1; i <= n; i++) {
263 php_printf("%s", lua_tostring(L, i));
266 return 0;
267 } /* }}} */
269 static void php_lua_object_dtor(void *object, zend_object_handle handle TSRMLS_DC) /* {{{ */
271 php_lua_object *intern = (php_lua_object*)object;
272 zend_object_std_dtor(&(intern->std) TSRMLS_CC);
274 long i;
275 for (i=0;i<intern->callback_count;i++)
276 efree(intern->callbacks[i]);
277 efree(intern->callbacks);
278 if (intern->L) {
279 lua_close(intern->L);
282 efree(intern);
283 } /* }}} */
285 static zval *php_lua_read_property(zval *obj, zval *prop, int type TSRMLS_DC) /* {{{ */
287 zval *retval;
288 lua_State *L = getLuaZ(obj);
290 LUA_STACK_START(L);
292 if (type != BP_VAR_R) {
293 php_error_docref(NULL TSRMLS_CC, E_WARNING, "No write access using read_property.");
294 ALLOC_INIT_ZVAL(retval);
295 return retval;
298 if (Z_TYPE_P(prop) == IS_STRING) {
299 MAKE_STD_ZVAL(retval);
300 lua_getfield(L, LUA_GLOBALSINDEX, Z_STRVAL_P(prop) TSRMLS_CC);
301 php_lua_get_zval_from_stack(L, -1, retval TSRMLS_CC);
302 Z_DELREF_P(retval);
303 } else {
304 ALLOC_INIT_ZVAL(retval);
307 lua_pop(L, 1);
309 LUA_STACK_END(L);
311 return retval;
312 } /* }}} */
315 static void php_lua_write_real_property(lua_State *L,int index,zval *prop, zval *value TSRMLS_DC) /* {{{ */
317 LUA_STACK_START(L);
318 php_lua_push_zval(L, prop TSRMLS_CC);
319 php_lua_push_zval(L, value TSRMLS_CC);
321 lua_settable(L, index);
322 LUA_STACK_END(L);
323 } /* }}} */
327 static void php_lua_write_property(zval *obj, zval *prop, zval *value TSRMLS_DC) /* {{{ */
329 /* TODO: Use proper type for lua and separate only when needed */
330 lua_State *L = getLuaZ(obj);
332 php_lua_write_real_property(L,LUA_GLOBALSINDEX,prop,value TSRMLS_CC);
333 } /* }}} */
335 static int php_lua_atpanic(lua_State *L) { /* {{{ */
336 TSRMLS_FETCH();
337 php_error_docref(NULL TSRMLS_CC, E_WARNING, "lua panic (%s)", lua_tostring(L, 1));
338 lua_pop(L, 1);
339 zend_bailout();
340 return 0;
341 } /* }}} */
343 static zend_object_value php_lua_create_object(zend_class_entry *ce TSRMLS_DC) /* {{{ */
345 zval tmp;
346 zend_object_value retval;
347 php_lua_object *intern;
348 lua_State *L;
350 L = lua_newstate(php_lua_alloc, NULL);
351 lua_atpanic(L, php_lua_atpanic);
353 intern = ecalloc(1, sizeof(php_lua_object));
354 intern->L = L;
355 intern->callback_count=0;
356 intern->callbacks=emalloc(sizeof(zval*));
357 zend_object_std_init(&(intern->std), ce TSRMLS_CC);
358 zend_hash_copy(intern->std.properties,
359 &ce->default_properties, (copy_ctor_func_t) zval_add_ref,
360 (void *) &tmp, sizeof(zval *));
362 retval.handle = zend_objects_store_put(intern, php_lua_object_dtor, NULL, NULL TSRMLS_CC);
363 retval.handlers = &lua_handlers;
364 return retval;
365 } /* }}} */
367 static int php_lua_callback(lua_State *L) /* {{{ */
369 php_lua_object *object=(php_lua_object*)lua_topointer(L, lua_upvalueindex(1));
370 long selected_callback_index=(long)lua_tonumber(L, lua_upvalueindex(2));
371 zval *return_value;
373 ALLOC_INIT_ZVAL(return_value);
375 if (!zend_is_callable(object->callbacks[selected_callback_index],0,NULL))
376 return;
378 zval **params;
379 int n = lua_gettop(L); /* number of arguments */
381 params=emalloc(n*sizeof(zval));
383 int i;
384 for (i = 1; i <= n; i++) {
385 ALLOC_INIT_ZVAL(params[i-1]);
386 /* php_lua_get_zval_from_stack won't work with positive indices */
387 php_lua_get_zval_from_stack(L,-n-1+i,params[i-1] TSRMLS_CC);
390 /* XXX no check - do we need one? :S */
391 /* johannes said i should use zend_call_method but this only allows up to 2 parameters?! */
392 call_user_function(EG(function_table),NULL,object->callbacks[selected_callback_index],return_value,n,params TSRMLS_CC);
394 /* hmm...what if the result is NULL? should php return a return value (NULL) then or just return 0? :S */
395 php_lua_push_zval(L,return_value TSRMLS_CC);
397 for (i = 0; i < n; i++) {
398 zval_ptr_dtor(&params[i]);
400 efree(params);
402 zval_ptr_dtor(&return_value);
404 /* PHP doesn't support multiple return values so this will always be 1 */
405 return 1;
406 } /* }}} */
408 static void php_lua_call_table_with_arguments(lua_State *L,int level,int table_index,char *function,int propagate_self,zval *args,zval *return_value) /* {{{ */
410 lua_getfield(L,table_index,function);
411 if (lua_type(L,lua_gettop(L)) != LUA_TFUNCTION) {
412 lua_pop(L, lua_gettop(L) - level);
413 php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid lua callback. '%s' is not a defined function",function);
414 return;
417 /* push the table on the stack as the first argument */
418 if (propagate_self)
419 lua_pushvalue(L,table_index + lua_gettop(L));
421 zend_hash_apply_with_argument(Z_ARRVAL_P(args), php_lua_push_apply_func, (void *)L TSRMLS_CC);
423 if (lua_pcall(L, zend_hash_num_elements(Z_ARRVAL_P(args)) + propagate_self, LUA_MULTRET, 0) != 0) {
424 php_error_docref(NULL TSRMLS_CC, E_WARNING, "error running lua function `%s': %s", function, lua_tostring(L, -1));
425 lua_pop(L, lua_gettop(L) - level);
426 return;
429 /* always return an array. otherwise we couldn't distinguish between a table return or a multi return */
430 array_init(return_value);
431 int retcount = lua_gettop(L) - level;
432 int i;
433 zval *val;
435 for (i = -retcount; i < 0; i++)
437 MAKE_STD_ZVAL(val);
438 php_lua_get_zval_from_stack(L, i, val TSRMLS_CC);
439 add_next_index_zval(return_value, val);
441 lua_pop(L, retcount);
443 return;
444 } /* }}} */
446 static void php_lua_call_table_function(INTERNAL_FUNCTION_PARAMETERS,int propagate_self) /* {{{ */
448 zval *callback,*args;
449 zval **lua_table,**lua_function;
450 int array_count,level;
451 lua_State *L;
453 L=getLua();
454 LUA_STACK_START(L);
456 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "za", &callback, &args) == FAILURE) {
457 return;
460 array_count=zend_hash_num_elements(Z_ARRVAL_P(callback));
461 if (array_count!=2) {
462 LUA_STACK_END(L);
463 php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid callback supplied. must contain exactly 2 elements");
464 return;
466 if (zend_hash_index_find(Z_ARRVAL_P(callback), 0, (void**)&lua_table) == FAILURE) {
467 php_error_docref(NULL TSRMLS_CC, E_WARNING, "callback index 0 is empty");
468 return;
470 if (zend_hash_index_find(Z_ARRVAL_P(callback), 1, (void**)&lua_function) == FAILURE) {
471 php_error_docref(NULL TSRMLS_CC, E_WARNING, "callback index 1 is empty");
472 return;
474 lua_getglobal(L,Z_STRVAL_PP(lua_table));
475 if (lua_type(L,lua_gettop(L)) != LUA_TTABLE) {
476 lua_pop(L, -1);
477 php_error_docref(NULL TSRMLS_CC, E_WARNING, "trying to call an invalid table '%s'",Z_STRVAL_PP(lua_table));
478 return;
480 level=lua_gettop(L);
482 php_lua_call_table_with_arguments(L,level,-1,Z_STRVAL_PP(lua_function),propagate_self,args,return_value);
484 /* remove the table which is still on top */
485 lua_pop(L,-1);
487 LUA_STACK_END(L);
488 } /* }}} */
490 /* {{{ */
491 static int php_lua_binary_zval_writer(lua_State* L, const void* p,size_t size, void* u)
493 Z_STRVAL_P((zval*)u)=erealloc(Z_STRVAL_P((zval*)u),(Z_STRLEN_P((zval*)u)+1+size)*sizeof(char));
494 memcpy(&Z_STRVAL_P((zval*)u)[Z_STRLEN_P((zval*)u)],p,size);
495 Z_STRLEN_P((zval*)u)=Z_STRLEN_P((zval*)u)+size;
496 Z_STRVAL_P((zval*)u)[Z_STRLEN_P((zval*)u)]='\0';
497 return 0;
499 /* }}} */
501 #define RETURN_STR "return %s"
504 /* {{{ lua::__construct()
505 Create new LUA instance */
506 PHP_METHOD(lua, __construct)
508 lua_State *L = getLua();
509 // mop: open standard libs if desired
510 if (lua_globals.load_standard_libs)
511 luaL_openlibs(L);
513 lua_register(L, "print", php_lua_print);
515 /* }}} */
517 /* {{{ lua::__call(string method, array args [, int nresults])
518 Call a lua function from within PHP */
519 PHP_METHOD(lua, __call)
521 int level, retcount;
522 char *function, *func;
523 int function_len;
524 zval *args;
525 long nresults = LUA_MULTRET;
526 lua_State *L = getLua();
528 LUA_STACK_START(L);
530 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|l", &function, &function_len, &args, &nresults) == FAILURE) {
531 return;
534 level = lua_gettop(L);
536 spprintf(&func, sizeof(RETURN_STR)-2-1+function_len, RETURN_STR, function);
537 if (luaL_dostring(L, func)) {
538 efree(func);
539 php_error_docref(NULL TSRMLS_CC, E_WARNING, "error looking up lua function `%s': %s", function, lua_tostring(L, -1));
540 lua_pop(L, lua_gettop(L) - level);
541 LUA_STACK_END(L);
542 return;
544 efree(func);
546 zend_hash_apply_with_argument(Z_ARRVAL_P(args), php_lua_push_apply_func, (void *)L TSRMLS_CC);
548 if (lua_pcall(L, zend_hash_num_elements(Z_ARRVAL_P(args)), nresults, 0) != 0) {
549 php_error_docref(NULL TSRMLS_CC, E_WARNING, "error running lua function `%s': %s", function, lua_tostring(L, -1));
550 lua_pop(L, lua_gettop(L) - level);
551 LUA_STACK_END(L);
552 return;
555 retcount = lua_gettop(L) - level;
557 if (retcount == 0) {
558 /* No vlaue returned -> return null */
559 } else {
560 /* multiple return values -> build an array */
561 int i;
562 zval *val;
564 array_init(return_value);
565 for (i = -retcount; i < 0; i++)
567 MAKE_STD_ZVAL(val);
568 php_lua_get_zval_from_stack(L, i, val TSRMLS_CC);
569 add_next_index_zval(return_value, val);
571 lua_pop(L, retcount);
574 LUA_STACK_END(L);
575 return;
578 /* {{{ lua::call_function(string function, array args)
579 Call a lua function from within PHP */
580 PHP_METHOD(lua, call_function)
582 char *function;
583 int function_len;
584 zval *args;
585 lua_State *L;
586 int level;
588 L=getLua();
589 LUA_STACK_START(L);
591 level=lua_gettop(L);
593 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa", &function, &function_len, &args) == FAILURE) {
594 return;
597 php_lua_call_table_with_arguments(L,level,LUA_GLOBALSINDEX,function,0,args,return_value);
599 LUA_STACK_END(L);
602 /* {{{ lua::call_table(array lua_callback, array args)
603 Call a lua table from within PHP (lua_table.lua_function()) */
604 PHP_METHOD(lua, call_table)
606 php_lua_call_table_function(INTERNAL_FUNCTION_PARAM_PASSTHRU,0);
609 /* {{{ lua::call_table_self(array lua_callback, array args)
610 Call a lua table from within PHP and propagate self (lua_table:lua_function()) */
611 PHP_METHOD(lua, call_table_self)
613 php_lua_call_table_function(INTERNAL_FUNCTION_PARAM_PASSTHRU,1);
616 /* {{{ void lua::evaluate(string code)
617 Evaluates code with lua */
618 PHP_METHOD(lua, evaluate)
620 int error;
621 int code_len;
622 char *code;
623 lua_State *L = getLua();
625 LUA_STACK_START(L);
627 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &code, &code_len) == FAILURE) {
628 return;
631 error = luaL_loadbuffer(L, code, code_len, "line") || lua_pcall(L, 0, LUA_MULTRET, 0);
632 if (error) {
633 php_error_docref(NULL TSRMLS_CC, E_WARNING, "lua error: %s", lua_tostring(L, -1));
634 lua_pop(L, 1); /* pop error message from the stack */
637 /* always return an array. otherwise we couldn't distinguish between a table return or a multi return */
638 array_init(return_value);
639 int retcount = lua_gettop(L);
640 int i;
641 zval *val;
643 for (i = -retcount; i < 0; i++)
645 MAKE_STD_ZVAL(val);
646 php_lua_get_zval_from_stack(L, i, val TSRMLS_CC);
647 add_next_index_zval(return_value, val);
649 lua_pop(L, retcount);
651 LUA_STACK_END(L);
653 /* }}} */
655 /* {{{ void lua::evaluatefile(string file)
656 Evaluates a lua script */
657 PHP_METHOD(lua, evaluatefile)
659 int error;
660 int file_len;
661 char *file;
662 lua_State *L = getLua();
664 LUA_STACK_START(L);
666 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &file_len) == FAILURE) {
667 return;
670 if (php_check_open_basedir(file TSRMLS_CC) || (PG(safe_mode) && !php_checkuid(file, "rb+", CHECKUID_CHECK_MODE_PARAM))) {
671 LUA_STACK_END(L);
672 RETURN_FALSE;
675 error = luaL_dofile(L, file);
677 if (error) {
678 php_error_docref(NULL TSRMLS_CC, E_WARNING, "lua error: %s", lua_tostring(L, -1));
679 lua_pop(L, 1);
682 array_init(return_value);
683 int retcount = lua_gettop(L);
684 int i;
685 zval *val;
687 for (i = -retcount; i < 0; i++)
689 MAKE_STD_ZVAL(val);
690 php_lua_get_zval_from_stack(L, i, val TSRMLS_CC);
691 add_next_index_zval(return_value, val);
693 lua_pop(L, retcount);
695 LUA_STACK_END(L);
697 /* }}} */
699 /* {{{ string lua::getVersion()
700 Return Lua's version */
701 PHP_METHOD(lua, getversion)
703 RETURN_STRING(LUA_RELEASE, 1);
705 /* }}} */
707 /* {{{ */
708 PHP_METHOD(lua,expose_function)
710 zval *callback;
711 char *lua_name;
712 long len;
714 php_lua_object *object=getLuaY();
715 lua_State *L = object->L;
717 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"sz",&lua_name,&len,&callback) == FAILURE)
718 return;
720 if (zend_is_callable(callback,0,NULL)) {
721 lua_pushlightuserdata(L,object);
722 lua_pushnumber(L,object->callback_count);
723 lua_pushcclosure(L, php_lua_callback,2);
724 lua_setglobal(L, lua_name);
726 /* hmm...out of memory check? */
727 object->callbacks=erealloc(object->callbacks,sizeof(zval)*(object->callback_count+1));
729 ALLOC_INIT_ZVAL(object->callbacks[object->callback_count]);
730 *object->callbacks[object->callback_count] = *callback;
731 zval_copy_ctor(object->callbacks[object->callback_count]);
733 object->callback_count++;
735 /* }}} */
737 /* {{{ */
738 PHP_METHOD(lua,compile)
740 char *chunk;
741 long len;
742 int error;
744 lua_State *L = lua_newstate(php_lua_alloc, NULL);
745 lua_atpanic(L, php_lua_atpanic);
747 LUA_STACK_START(L);
749 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,"s",&chunk,&len) == FAILURE)
751 lua_close(L);
752 return;
755 error = luaL_loadbuffer(L, chunk, len, "line");
756 if (error) {
757 php_error_docref(NULL TSRMLS_CC, E_WARNING, "lua error: %s", lua_tostring(L, -1));
758 lua_pop(L, 1); /* pop error message from the stack */
759 lua_close(L);
760 return;
763 RETVAL_STRING("",1);
765 error=lua_dump(L,php_lua_binary_zval_writer,return_value);
766 lua_pop(L, 1); /* clean stack */
767 LUA_STACK_END(L);
768 lua_close(L);
769 if (error) {
770 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't dump code");
771 RETURN_NULL();
775 /* {{{ lua_functions[] */
776 zend_function_entry lua_functions[] = {
777 {NULL, NULL, NULL}
779 /* }}} */
781 /* {{{ ARG_INFO */
783 ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_call, 0, 0, 2)
784 ZEND_ARG_INFO(0, method)
785 ZEND_ARG_INFO(0, args)
786 ZEND_END_ARG_INFO()
788 ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_call_table, 0, 0, 2)
789 ZEND_ARG_INFO(0, callback)
790 ZEND_ARG_INFO(0, args)
791 ZEND_END_ARG_INFO()
793 ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_call_function, 0, 0, 2)
794 ZEND_ARG_INFO(0, function)
795 ZEND_ARG_INFO(0, args)
796 ZEND_END_ARG_INFO()
798 ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_evaluate, 0, 0, 1)
799 ZEND_ARG_INFO(0, code)
800 ZEND_END_ARG_INFO()
802 ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_evaluatefile, 0, 0, 1)
803 ZEND_ARG_INFO(0, file)
804 ZEND_END_ARG_INFO()
806 ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_expose_function, 0, 0, 1)
807 ZEND_ARG_INFO(0, callback)
808 ZEND_END_ARG_INFO()
810 ZEND_BEGIN_ARG_INFO_EX(arginfo_lua_compile, 0, 0, 1)
811 ZEND_ARG_INFO(0, chunk)
812 ZEND_END_ARG_INFO()
814 /* }}} */
816 /* {{{ lua_class_functions[] */
817 zend_function_entry lua_class_functions[] = {
818 PHP_ME(lua, __construct, NULL, ZEND_ACC_PUBLIC)
819 PHP_ME(lua, __call, arginfo_lua_call, ZEND_ACC_PUBLIC)
820 PHP_ME(lua, call_function, arginfo_lua_call_function, ZEND_ACC_PUBLIC)
821 PHP_ME(lua, call_table, arginfo_lua_call_table, ZEND_ACC_PUBLIC)
822 PHP_ME(lua, call_table_self, arginfo_lua_call_table, ZEND_ACC_PUBLIC)
823 PHP_ME(lua, evaluate, arginfo_lua_evaluate, ZEND_ACC_PUBLIC)
824 PHP_ME(lua, evaluatefile, arginfo_lua_evaluatefile, ZEND_ACC_PUBLIC)
825 PHP_ME(lua, getversion, NULL, ZEND_ACC_PUBLIC)
826 PHP_ME(lua, expose_function, arginfo_lua_expose_function, ZEND_ACC_PUBLIC)
827 PHP_ME(lua, compile, arginfo_lua_compile, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
828 {NULL, NULL, NULL}
830 /* }}} */
832 #ifdef COMPILE_DL_LUA
833 ZEND_GET_MODULE(lua)
834 #endif
836 /* {{{ PHP_INI
838 PHP_INI_BEGIN()
839 STD_PHP_INI_BOOLEAN("lua.load_standard_libs","1", PHP_INI_ALL, OnUpdateBool, load_standard_libs, zend_lua_globals, lua_globals)
840 PHP_INI_END()
841 /* }}} */
843 /* {{{ php_lua_init_globals
845 static void php_lua_init_globals(zend_lua_globals *lua_globals)
848 /* }}} */
850 /* {{{ PHP_MINIT_FUNCTION
852 PHP_MINIT_FUNCTION(lua)
854 REGISTER_INI_ENTRIES();
856 zend_class_entry ce;
857 INIT_CLASS_ENTRY(ce, "lua", lua_class_functions);
858 lua_ce = zend_register_internal_class(&ce TSRMLS_CC);
859 lua_ce->create_object = php_lua_create_object;
860 memcpy(&lua_handlers, zend_get_std_object_handlers(),
861 sizeof(zend_object_handlers));
862 lua_handlers.write_property = php_lua_write_property;
863 lua_handlers.read_property = php_lua_read_property;
864 lua_ce->ce_flags |= ZEND_ACC_FINAL;
866 zend_declare_class_constant_long(lua_ce, "MULTRET", sizeof("MULTRET")-1, LUA_MULTRET TSRMLS_CC);
868 ZEND_INIT_MODULE_GLOBALS(lua, php_lua_init_globals, NULL);
870 return SUCCESS;
872 /* }}} */
874 /* {{{ PHP_MSHUTDOWN_FUNCTION
876 PHP_MSHUTDOWN_FUNCTION(lua)
878 UNREGISTER_INI_ENTRIES();
879 return SUCCESS;
881 /* }}} */
883 /* {{{ PHP_RINIT_FUNCTION
885 PHP_RINIT_FUNCTION(lua)
887 return SUCCESS;
889 /* }}} */
891 /* {{{ PHP_RSHUTDOWN_FUNCTION
893 PHP_RSHUTDOWN_FUNCTION(lua)
895 return SUCCESS;
897 /* }}} */
899 /* {{{ PHP_MINFO_FUNCTION
901 PHP_MINFO_FUNCTION(lua)
903 php_info_print_table_start();
904 php_info_print_table_row(2, "lua support", "enabled");
905 php_info_print_table_row(2, "lua extension version", EXT_LUA_VERSION);
906 php_info_print_table_row(2, "lua release", LUA_RELEASE);
907 php_info_print_table_row(2, "lua copyright", LUA_COPYRIGHT);
908 php_info_print_table_row(2, "lua authors", LUA_AUTHORS);
909 php_info_print_table_end();
911 DISPLAY_INI_ENTRIES();
913 /* }}} */
915 /* {{{ lua_module_entry
917 zend_module_entry lua_module_entry = {
918 STANDARD_MODULE_HEADER,
919 "lua",
920 lua_functions,
921 PHP_MINIT(lua),
922 PHP_MSHUTDOWN(lua),
923 PHP_RINIT(lua),
924 PHP_RSHUTDOWN(lua),
925 PHP_MINFO(lua),
926 EXT_LUA_VERSION,
927 STANDARD_MODULE_PROPERTIES
929 /* }}} */
932 * Local variables:
933 * tab-width: 4
934 * c-basic-offset: 4
935 * vim: set noet sw=4 ts=4:
936 * vim600: noet sw=4 ts=4 fdm=marker:
937 * End: