diff --git a/Makefile b/Makefile index 560a258..e8c0b62 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ ifeq ($(PHPDIR),) PHPDIR=/usr endif -PHPCONFIG=$(PHPDIR)/bin/php-config +PHPCONFIG=$(PHPDIR)/bin/php-config56 export PATH := $(PHPDIR)/bin:$(PATH) export CFLAGS := $(shell export PATH=$(PATH) && $(PHPCONFIG) --includes) @@ -14,10 +14,12 @@ export CGO_CFLAGS := $(CFLAGS) $(CGO_CFLAGS) export CGO_LDFLAGS := $(LDFLAGS) $(CGO_LDFLAGS) all: - go install ./zend - go install ./phpgo - go build -v -linkshared -buildmode=c-shared -o hello.so examples/hello.go - # php -d extension=./hello.so examples/hello.php + # go install ./zend + # CGO_ENABLE=1 go install ./phpgo + # CGO_ENABLE=1 go build -gcflags="-newexport=0 -ssa=0" -v -buildmode=c-shared -o hello.so miniphpgo.go + CGO_ENABLE=1 go build -v -buildmode=c-shared -o hello.so miniso.go + gcc main.c -ldl + # php -d extension=./hello.so miniphpgo.php clean: rm -f ../../pkg/linux_amd64/zend.a diff --git a/examples/hello.go b/examples/hello.go deleted file mode 100644 index cf1a726..0000000 --- a/examples/hello.go +++ /dev/null @@ -1,106 +0,0 @@ -package main - -import "log" -import "reflect" -import "math/rand" -import "time" -import "github.com/kitech/php-go/phpgo" - -type PGDemo struct { -} - -func NewPGDemo() *PGDemo { - log.Println("NewPGDemo...") - return &PGDemo{} -} - -func (this *PGDemo) Hello1() int { - rn := rand.Intn(65536) - log.Println("called in go scope, hello1 method", rn) - return rn -} - -func (this *PGDemo) Hello2() { - -} - -func (this *PGDemo) Hello3() { - -} - -func (this *PGDemo) Hello4() { - -} - -func (this *PGDemo) Hello5() { - -} - -func (this *PGDemo) Hello6() { - -} - -func phpgo_hello() { - log.Println("ext user func called") -} - -func phpgo_hello3(a0 int, a1 string, a2 float64) { - log.Println("ext user func called222", a0, a1, a2) -} - -func phpgo_hello7(names []int64) { - log.Println(names) -} - -func phpgo_hello8(names map[string]string) { - log.Println(names) -} - -func module_startup(ptype int, module_number int) int { - println("module_startup", ptype, module_number) - return rand.Int() -} -func module_shutdown(ptype int, module_number int) int { - println("module_shutdown", ptype, module_number) - return rand.Int() -} -func request_startup(ptype int, module_number int) int { - println("request_startup", ptype, module_number) - return rand.Int() -} -func request_shutdown(ptype int, module_number int) int { - println("request_shutdown", ptype, module_number) - return rand.Int() -} - -func init() { - log.Println("run us init...") - rand.Seed(time.Now().UnixNano()) - - f2 := func() int { - log.Println("ext user func called222 closure") - return 567 - } - - phpgo.InitExtension("pg0", "") - phpgo.RegisterInitFunctions(module_startup, module_shutdown, request_startup, request_shutdown) - - phpgo.AddFunc("foo_hello", phpgo_hello) - // phpgo.AddFunc("foo_hello2", phpgo_hello2) - phpgo.AddFunc("foo_hello2", f2) - phpgo.AddFunc("foo_hello3", phpgo_hello3) - phpgo.AddFunc("foo_hello7", phpgo_hello7) - phpgo.AddFunc("foo_hello8", phpgo_hello8) - - // - dm := NewPGDemo() - log.Println("method fn:", dm.Hello1, reflect.TypeOf(dm.Hello1), NewPGDemo) - - phpgo.AddClass("PGDemo", NewPGDemo) - // zend.AddMethod("PGDemo", "hello1", PGDemo.hello1) -} - -func main() { - panic("wtf") - log.Println("run here for what?") -} diff --git a/examples/hello.php b/examples/hello.php deleted file mode 100644 index b6e3de0..0000000 --- a/examples/hello.php +++ /dev/null @@ -1,10 +0,0 @@ -Hello1(); -var_dump($r); - diff --git a/main.c b/main.c new file mode 100644 index 0000000..dcac01e --- /dev/null +++ b/main.c @@ -0,0 +1,13 @@ +#include +#include +#include + +int main(int argc, char **argv) +{ + void *soh = dlopen("./hello.so", RTLD_NOW); + void *(*get_mod)(); + get_mod = dlsym(soh, "get_module"); + void *v = get_mod(); + printf("soh: %p, %p, %p\n", soh, get_mod, v); + return 0; +} diff --git a/miniso.go b/miniso.go new file mode 100644 index 0000000..941f941 --- /dev/null +++ b/miniso.go @@ -0,0 +1,17 @@ +package main + +/* + */ +import "C" +import "unsafe" + +import "fmt" + +// +//export get_module +func get_module() unsafe.Pointer { + fmt.Println("hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh") + return unsafe.Pointer(uintptr(5)) +} + +func main() {} diff --git a/phpgo/extension.c b/phpgo/extension.c deleted file mode 100644 index 0601c2d..0000000 --- a/phpgo/extension.c +++ /dev/null @@ -1,670 +0,0 @@ -#include -#include -#include -#include - -/** - * PHP includes - */ -#include -#include -#include -#include -#include -#include - -#ifdef ZTS -#include "TSRM.h" -#endif - -#include "_cgo_export.h" - -// #include "sztypes.h" -#include "../zend/goapi.h" - - -#define GLOBAL_VCLASS_ID 0 -#define MAX_ARG_NUM 10 -#define MFN 128 // MAX_FUNC_NUM -#define MCN 128 // MAX_CLASS_NUM - -// TODO PHP7支持 -static zend_function_entry g_funcs[MCN][MFN] = {0}; -static zend_class_entry g_centries[MCN] = {0}; -static zend_module_entry g_entry = {0}; - -// ZEND_DECLARE_MODULE_GLOBALS(phpgo); -// static void init_globals(zend_phpgo_globals *globals) {} - -static int(*phpgo_module_startup_cbfunc)(int, int) = 0; -static int(*phpgo_module_shutdown_cbfunc)(int, int) = 0; -static int(*phpgo_request_startup_cbfunc)(int, int) = 0; -static int(*phpgo_request_shutdown_cbfunc)(int, int) = 0; - -int phpgo_module_startup_func(int type, int module_number TSRMLS_DC) -{ - if (phpgo_module_startup_cbfunc) { - return call_golang_function(phpgo_module_startup_cbfunc, type, module_number, 0, 0, 0, 0, 0, 0, 0, 0); - } - return 0; -} - -int phpgo_module_shutdown_func(int type, int module_number TSRMLS_DC) -{ - if (phpgo_module_shutdown_cbfunc) { - return call_golang_function(phpgo_module_shutdown_cbfunc, type, module_number, 0, 0, 0, 0, 0, 0, 0, 0); - } - return 0; -} - -int phpgo_request_startup_func(int type, int module_number TSRMLS_DC) -{ - if (phpgo_request_startup_cbfunc) { - return call_golang_function(phpgo_request_startup_cbfunc, type, module_number, 0, 0, 0, 0, 0, 0, 0, 0); - } - return 0; -} - -int phpgo_request_shutdown_func(int type, int module_number TSRMLS_DC) -{ - if (phpgo_request_shutdown_cbfunc) { - return call_golang_function(phpgo_request_shutdown_cbfunc, type, module_number, 0, 0, 0, 0, 0, 0, 0, 0); - } - return 0; -} - -void phpgo_register_init_functions(void *module_startup_func, void *module_shutdown_func, - void *request_startup_func, void *request_shutdown_func) -{ - phpgo_module_startup_cbfunc = (int (*)(int, int))module_startup_func; - phpgo_module_shutdown_cbfunc = (int (*)(int, int))module_shutdown_func; - phpgo_request_startup_cbfunc = (int (*)(int, int))request_startup_func; - phpgo_request_shutdown_cbfunc = (int (*)(int, int))request_shutdown_func; - return; -} - -// TODO module name from args -// TODO module version from args -// TODO module startup/shutdown... function from args, or set seperator -void *phpgo_get_module(char *name, char *version) { - zend_module_entry te = { - STANDARD_MODULE_HEADER, - name, // "phpgo", - g_funcs[GLOBAL_VCLASS_ID], - phpgo_module_startup_func, - phpgo_module_shutdown_func, - phpgo_request_startup_func, /* Replace with NULL if there's nothing to do at request start */ - phpgo_request_shutdown_func, /* Replace with NULL if there's nothing to do at request end */ - NULL, - version, // "1.0", - STANDARD_MODULE_PROPERTIES - }; - - memcpy(&g_entry, &te, sizeof(zend_module_entry)); - return &g_entry; -} - -int phpgo_get_module_number() { - return g_entry.module_number; -} - -struct phpgo_callback_signature { - char argtys[10]; - int retys; - int varidict; -}; - -static char *phpgo_argtys[MCN*MFN] = {0}; -static int phpgo_retys[MCN*MFN] = {0}; -static struct phpgo_callback_signature phpgo_cbsigs[MCN*MFN] = {0}; - -// TODO 支持php callable类型,方便实现回调? -// TODO 支持php array类型?有点复杂。 -char *type2name(int type) -{ - switch (type) { - case IS_ARRAY: - return "array"; - case IS_STRING: - return "string"; - case IS_DOUBLE: - return "double"; -#ifdef ZEND_ENGINE_3 - case _IS_BOOL: -#else - case IS_BOOL: -#endif - return "bool"; - case IS_LONG: - return "long"; -#ifdef ZEND_ENGINE_3 - case IS_UNDEF: -#endif - case IS_NULL: - return "void"; - case IS_OBJECT: - return "object"; - case IS_RESOURCE: - return "pointer"; - case IS_CALLABLE: - return "callable"; - case IS_LEXICAL_VAR: - return "var"; - default: - return "unknown"; - } - return NULL; - } - -// 计算要转换的参数个数,有效的参数个数 -// php提供的参数个数要>=go函数需要的参数个数 -// 如果go是变长参数个数, 则计算出 最小 值,并把php提供的所有参数全部传递 -static int phpgo_function_num_args(int cbid, int supply_num_args) -{ - int num_args = phpgo_argtys[cbid] != NULL ? strlen(phpgo_argtys[cbid]) : 0; - - return num_args; -} - -// PHP函数参数转换为go类型的参数 -static void* phpgo_function_conv_arg(int cbid, int idx, char ch, int zty, zval **zarg) -{ - int prmty = zty; - void *rv = NULL; - - if (ch == 's') { - if (prmty != IS_STRING) { - zend_error(E_WARNING, "Parameters type not match, need (%c), given: %s", - ch, type2name(prmty)); - } - - convert_to_string_ex(zarg); - char *arg = Z_STRVAL_PP(zarg); - printf("arg%d(%c), %s(%d)\n", idx, ch, arg, Z_STRLEN_PP(zarg)); - goapi_new_value(GT_String, (uint64_t)arg, &rv); - } else if (ch == 'l') { - if (prmty != IS_LONG) { - zend_error(E_WARNING, "Parameters type not match, need (%c), given: %s", - ch, type2name(prmty)); - } - - convert_to_long_ex(zarg); - long arg = (long)Z_LVAL_PP(zarg); - printf("arg%d(%c), %d\n", idx, ch, arg); - goapi_new_value(GT_Int64, (uint64_t)arg, &rv); - } else if (ch == 'b') { - convert_to_boolean_ex(zarg); - zend_bool arg = (zend_bool)Z_BVAL_PP(zarg); - goapi_new_value(GT_Bool, (uint64_t)arg, &rv); - } else if (ch == 'd') { - convert_to_double_ex(zarg); - double arg = (double)Z_DVAL_PP(zarg); - double* parg = calloc(1, sizeof(double)); - *parg = (double)Z_DVAL_PP(zarg); - // argv[idx] = (void*)(ulong)arg; // error - // memcpy(&argv[idx], &arg, sizeof(argv[idx])); // ok - // float32(uintptr(ax)) - goapi_new_value(GT_Float64, (uint64_t)parg, &rv); - } else if (ch == 'a') { - if (Z_TYPE_PP(zarg) == IS_STRING) { - char *arg = Z_STRVAL_PP(zarg); - goapi_new_value(GT_String, (uint64_t)arg, &rv); -#ifdef ZEND_ENGINE_3 - } else if (Z_TYPE_PP(zarg) == _IS_BOOL) { -#else - } else if (Z_TYPE_PP(zarg) == IS_BOOL) { -#endif - zend_bool arg = (zend_bool)Z_BVAL_PP(zarg); - goapi_new_value(GT_Bool, (uint64_t)arg, &rv); - } else if (Z_TYPE_PP(zarg) == IS_DOUBLE) { - double* parg = calloc(1, sizeof(double)); - *parg = (double)Z_DVAL_PP(zarg); - goapi_new_value(GT_Float64, (uint64_t)parg, &rv); - } else if (Z_TYPE_PP(zarg) == IS_LONG) { - long arg = (long)Z_LVAL_PP(zarg); - goapi_new_value(GT_Int64, (uint64_t)arg, &rv); - } else if (Z_TYPE_PP(zarg) == IS_OBJECT) { - void *parg = (void*)zarg; - goapi_new_value(GT_UnsafePointer, (uint64_t)parg, &rv); - } else if (Z_TYPE_PP(zarg) == IS_RESOURCE) { - void *parg = (void*)zarg; - goapi_new_value(GT_UnsafePointer, (uint64_t)parg, &rv); - } else { - printf("arg%d(%c), %s(%d) unsported to Any\n", idx, ch, - type2name(Z_TYPE_PP(zarg)), Z_TYPE_PP(zarg)); - } - - // TODO array/vector convert - } else if (ch == 'v') { - HashTable *arr_hash = Z_ARRVAL_PP(zarg); - HashPosition pos; - zval **edata; - - for (zend_hash_internal_pointer_reset_ex(arr_hash, &pos); -#ifdef ZEND_ENGINE_3 - (edata = zend_hash_get_current_data_ex(arr_hash, &pos)) != NULL; -#else - zend_hash_get_current_data_ex(arr_hash, (void**)&edata, &pos) == SUCCESS; -#endif - zend_hash_move_forward_ex(arr_hash, &pos)) { - - if (rv == NULL) { - switch (Z_TYPE_PP(edata)) { - case IS_LONG: - goapi_array_new(GT_Int64, &rv); - break; - default: - goapi_array_new(GT_String, &rv); - break; - } - } - - switch (Z_TYPE_PP(edata)) { - case IS_LONG: - goapi_array_push(rv, (void*)Z_LVAL_PP(edata), &rv); - break; - default: - convert_to_string_ex(edata); - printf("array idx(%d)=T(%d=%s, val=%s)\n", pos, - Z_TYPE_PP(edata), type2name(Z_TYPE_PP(edata)), Z_STRVAL_PP(edata)); - goapi_array_push(rv, Z_STRVAL_PP(edata), &rv); - break; - } - } - - // TODO array/map convert - } else if (ch == 'm') { - // 简化成string=>string映射吧 - goapi_map_new(&rv); - - HashTable *arr_hash = Z_ARRVAL_PP(zarg); - HashPosition pos; - zval **edata; - - for (zend_hash_internal_pointer_reset_ex(arr_hash, &pos); -#ifdef ZEND_ENGINE_3 - (edata = zend_hash_get_current_data_ex(arr_hash, &pos)) != NULL; -#else - zend_hash_get_current_data_ex(arr_hash, (void**)&edata, &pos) == SUCCESS; -#endif - zend_hash_move_forward_ex(arr_hash, &pos)) { - - zval ekey = {0}; - zval *pekey = &ekey; - - zend_hash_get_current_key_zval_ex(arr_hash, &ekey, &pos); - - switch (Z_TYPE_PP(edata)) { - default: - convert_to_string_ex(&pekey); - convert_to_string_ex(edata); - printf("array idx(%d)=K(%s)=T(%d=%s, val=%s)\n", pos, Z_STRVAL_P(pekey), - Z_TYPE_PP(edata), type2name(Z_TYPE_PP(edata)), Z_STRVAL_PP(edata)); - goapi_map_add(rv, Z_STRVAL_P(pekey), Z_STRVAL_PP(edata)); - break; - } - } - - } else { - printf("arg%d(%c), %s(%d)\n", idx, ch, type2name(prmty), prmty); - zend_error(E_WARNING, "Parameters type not match, need (%c), given: %s", - ch, type2name(prmty)); - return NULL; - } - - return rv; -} - -static void phpgo_function_conv_args(int cbid, int supply_num_args, void *argv[]) -{ - int num_args = phpgo_function_num_args(cbid, supply_num_args); - // int supply_num_args = ZEND_NUM_ARGS(); - - zval **args[MAX_ARG_NUM] = {0}; - if (zend_get_parameters_array_ex(num_args, args) == FAILURE) { - printf("param count error: %d\n", num_args); - WRONG_PARAM_COUNT; - return; - } - - // void *argv[MAX_ARG_NUM] = {0}; - printf("parse params: %d\n", num_args); - for (int idx = 0; idx < num_args-1; idx ++) { - printf("arg%d, type=%d\n", idx, Z_TYPE_PP(args[idx])); - int prmty = Z_TYPE_PP(args[idx]); - char ch = phpgo_argtys[cbid][idx]; - zval **zarg = args[idx]; - - argv[idx] = phpgo_function_conv_arg(cbid, idx, ch, prmty, zarg); - } - - return; -} - -static void phpgo_method_conv_args(int cbid, int supply_num_args, void *argv[]) -{ - int num_args = phpgo_function_num_args(cbid, supply_num_args); - // int supply_num_args = ZEND_NUM_ARGS(); - - zval **args[MAX_ARG_NUM] = {0}; - if (zend_get_parameters_array_ex(num_args-1, args) == FAILURE) { - printf("param count error: %d\n", num_args); - WRONG_PARAM_COUNT; - return; - } - - // void *argv[MAX_ARG_NUM] = {0}; - printf("parse params: %d\n", num_args); - for (int idx = 0; idx < num_args-1; idx ++) { - printf("arg%d, type=%d\n", idx, Z_TYPE_PP(args[idx])); - int prmty = Z_TYPE_PP(args[idx]); - char ch = phpgo_argtys[cbid][idx+1]; - zval **zarg = args[idx]; - - argv[idx] = phpgo_function_conv_arg(cbid, idx, ch, prmty, zarg); - } - - return; -} - - -// go类型的返回值转换为PHP类型的变量值 -static int phpgo_function_conv_ret(int cbid, void *p0, zval *return_value) -{ - RETVAL_LONG(5); - - printf("convert ret: %p, type: %d(%s)\n", - p0, phpgo_retys[cbid], type2name(phpgo_retys[cbid])); - - uint64_t rv = (uint64_t)goapi_get_value(p0); - // 返回值解析转换 - switch (phpgo_retys[cbid]) { - case IS_STRING: -#ifdef ZEND_ENGINE_3 - RETVAL_STRINGL((char*)rv, strlen((char*)rv)); -#else - RETVAL_STRINGL((char*)rv, strlen((char*)rv), 1); -#endif - free((char*)rv); - break; - case IS_DOUBLE: - RETVAL_DOUBLE(*(double*)rv); - free((double*)rv); - break; -#ifdef ZEND_ENGINE_3 - case _IS_BOOL: -#else - case IS_BOOL: -#endif - RETVAL_BOOL(rv); - break; - case IS_LONG: - RETVAL_LONG(rv); - break; - case IS_NULL: - RETVAL_NULL(); - break; - case IS_RESOURCE: - RETVAL_NULL(); - break; - default: - // wtf? - zend_error(E_WARNING, "unrecognized return value: %d.", phpgo_retys[cbid]); - break; - } - - return 0; -} - - -#ifdef ZEND_ENGINE_3 -void phpgo_function_handler7(int cbid, zend_execute_data *execute_data, zval *return_value) -{ - zval *this_ptr = &execute_data->This; - zend_object* op; - if (NULL != this_ptr && IS_OBJECT == execute_data->This.u1.v.type) { - op = execute_data->This.value.obj; - } - printf("function handler called.%d, this=%p, atys=%s, op=%p\n", - cbid, this_ptr, phpgo_argtys[cbid], op); - - void *argv[MAX_ARG_NUM] = {0}; - if (this_ptr == NULL) { - phpgo_function_conv_args(cbid, (ZEND_NUM_ARGS()), argv); - } else { - phpgo_function_conv_args(cbid, (ZEND_NUM_ARGS()), argv); - } - - void* rv = NULL; - on_phpgo_function_callback_p(cbid, this_ptr, argv[0], argv[1], - argv[2], argv[3], argv[4], argv[5], - argv[6], argv[7], argv[8], argv[9], &rv, (void*) op); - printf("inout ret:%p\n", rv); - phpgo_function_conv_ret(cbid, rv, return_value); -} - -#else // php < 7.0 -void phpgo_function_handler(int cbid, int ht, zval *return_value, zval **return_value_ptr, - zval *this_ptr, int return_value_used TSRMLS_DC) -{ - void* op = NULL; - if (NULL != this_ptr && IS_OBJECT == this_ptr->type) { - zend_object_handle handle = this_ptr->value.obj.handle; - struct _store_object *obj; - obj = &EG(objects_store).object_buckets[handle].bucket.obj; - op = &obj->object; - } - printf("function handler called.%d, this=%p, atys=%s, op=%p\n", - cbid, this_ptr, phpgo_argtys[cbid], op); - - void *argv[MAX_ARG_NUM] = {0}; - if (this_ptr == NULL) { - phpgo_function_conv_args(cbid, (ZEND_NUM_ARGS()), argv); - } else { - phpgo_method_conv_args(cbid, (ZEND_NUM_ARGS()), argv); - } - - void* rv = NULL; - on_phpgo_function_callback_p(cbid, this_ptr, argv[0], argv[1], - argv[2], argv[3], argv[4], argv[5], - argv[6], argv[7], argv[8], argv[9], &rv, (void*) op); - printf("inout ret:%p\n", rv); - phpgo_function_conv_ret(cbid, rv, return_value); -} - -void phpgo_function_handler_dep(int cbid, int ht, zval *return_value, zval **return_value_ptr, - zval *this_ptr, int return_value_used TSRMLS_DC) -{ - printf("function handler called.%d, this=%p, atys=%s\n", - cbid, this_ptr, phpgo_argtys[cbid]); - - int num_args = phpgo_argtys[cbid] != NULL ? strlen(phpgo_argtys[cbid]) : 0; - int supply_num_args = ZEND_NUM_ARGS(); - - zval **args[10]; - if (zend_get_parameters_array_ex(num_args, args) == FAILURE) { - printf("param count error: %d\n", num_args); - WRONG_PARAM_COUNT; - return; - } - - void *argv[10] = {0}; - printf("parse params: %d\n", num_args); - for (int idx = 0; idx < num_args; idx ++) { - printf("arg%d, type=%d\n", idx, Z_TYPE_PP(args[idx])); - int prmty = Z_TYPE_PP(args[idx]); - char ch = phpgo_argtys[cbid][idx]; - zval **zarg = args[idx]; - - if (ch == 's') { - if (prmty != IS_STRING) { - zend_error(E_WARNING, "Parameters type not match, need (%c), given: %s", - ch, type2name(prmty)); - } - - convert_to_string_ex(zarg); - char *arg = Z_STRVAL_PP(zarg); - argv[idx] = arg; - printf("arg%d(%c), %s(%d)\n", idx, ch, arg, Z_STRLEN_PP(zarg)); - } else if (ch == 'l') { - if (prmty != IS_LONG) { - zend_error(E_WARNING, "Parameters type not match, need (%c), given: %s", - ch, type2name(prmty)); - } - - convert_to_long_ex(zarg); - long arg = (long)Z_LVAL_PP(zarg); - printf("arg%d(%c), %d\n", idx, ch, arg); - argv[idx] = (void*)arg; - } else if (ch == 'b') { - convert_to_boolean_ex(zarg); - zend_bool arg = (zend_bool)Z_BVAL_PP(zarg); - argv[idx] = (void*)(long)arg; - } else if (ch == 'd') { - convert_to_double_ex(zarg); - double arg = (double)Z_DVAL_PP(zarg); - double* parg = calloc(1, sizeof(double)); - *parg = (double)Z_DVAL_PP(zarg); - argv[idx] = parg; - // argv[idx] = (void*)(ulong)arg; // error - // memcpy(&argv[idx], &arg, sizeof(argv[idx])); // ok - // float32(uintptr(ax)) - } else { - printf("arg%d(%c), unknown\n", idx, ch); - zend_error(E_WARNING, "Parameters type not match, need (%c), given: %s", - ch, type2name(prmty)); - return; - } - } - - uint64_t rv = on_phpgo_function_callback(cbid, (uint64_t)this_ptr, - (uint64_t)argv[0], (uint64_t)argv[1], - (uint64_t)argv[2], (uint64_t)argv[3], - (uint64_t)argv[4], (uint64_t)argv[5], - (uint64_t)argv[6], (uint64_t)argv[7], - (uint64_t)argv[8], (uint64_t)argv[9]); - - // 返回值解析转换 - switch (phpgo_retys[cbid]) { - case IS_STRING: -#ifdef ZEND_ENGINE_3 - RETVAL_STRINGL((char*)rv, strlen((char*)rv)); -#else - RETVAL_STRINGL((char*)rv, strlen((char*)rv), 1); -#endif - free((char*)rv); - break; - case IS_DOUBLE: - RETVAL_DOUBLE(*(double*)rv); - free((double*)rv); - break; -#ifdef ZEND_ENGINE_3 - case _IS_BOOL: -#else - case IS_BOOL: -#endif - RETVAL_BOOL(rv); - break; - case IS_LONG: - RETVAL_LONG(rv); - break; - case IS_NULL: - RETVAL_NULL(); - break; - case IS_RESOURCE: - RETVAL_NULL(); - break; - default: - // wtf? - zend_error(E_WARNING, "unrecognized return value: %d.", phpgo_retys[cbid]); - break; - } - // TODO cleanup? -} -#endif - -static void (*phpgo_handlers[MCN*MFN])(INTERNAL_FUNCTION_PARAMETERS) = {0}; - -#ifdef ZEND_ENGINE_3 -#define PHPGO_FH_DECL(no) \ - void phpgo_function_handler_##no(INTERNAL_FUNCTION_PARAMETERS) { \ - phpgo_function_handler7(no, execute_data, return_value); \ - } -#else -#define PHPGO_FH_DECL(no) \ - void phpgo_function_handler_##no(INTERNAL_FUNCTION_PARAMETERS) { \ - phpgo_function_handler(no, ht, return_value, return_value_ptr, this_ptr, return_value_used); \ - } -#endif - -#define PHPGO_FH_ADD(no) phpgo_handlers[no] = phpgo_function_handler_##no - -// PHPGO_FH_DECL(0); PHPGO_FH_DECL(1); PHPGO_FH_DECL(2); PHPGO_FH_DECL(3); PHPGO_FH_DECL(4); -// PHPGO_FH_DECL(128); PHPGO_FH_DECL(129); PHPGO_FH_DECL(130); PHPGO_FH_DECL(131); PHPGO_FH_DECL(132); -#include "extension_syms.txt" -static int init_phpgo_handlers() { - // phpgo_handlers[0] = phpgo_function_handler_0; - // PHPGO_FH_ADD(0); PHPGO_FH_ADD(1); PHPGO_FH_ADD(2); PHPGO_FH_ADD(3); PHPGO_FH_ADD(4); - // PHPGO_FH_ADD(128); PHPGO_FH_ADD(129); PHPGO_FH_ADD(130); PHPGO_FH_ADD(131); PHPGO_FH_ADD(132); - #include "extension_adds.txt" - return 1; -} -static int init_phpgo_handlers_indicator = 0; - -int zend_add_function(int cidx, int fidx, int cbid, char *name, char *atys, int rety) -{ - // TODO thread? - if (init_phpgo_handlers_indicator == 0) { - init_phpgo_handlers_indicator = 1; - init_phpgo_handlers(); - } - - printf("add func %s at %d:%d=%d, %p, atys=%s, rety=%d\n", - name, cidx, fidx, cbid, phpgo_handlers[cbid], atys, rety); - - if (phpgo_handlers[cbid] == NULL) { - assert(phpgo_handlers[cbid] != NULL); - return -1; - } - - zend_function_entry *fe = &g_funcs[cidx][fidx]; - zend_function_entry e = {strdup(name), phpgo_handlers[cbid], NULL, 0, 0}; - memcpy(fe, &e, sizeof(e)); - - phpgo_argtys[cbid] = atys == NULL ? NULL : strdup(atys); - phpgo_retys[cbid] = rety; - - return 0; -} - -int zend_add_class(int cidx, char *cname) -{ - zend_class_entry *ce = &g_centries[cidx]; - INIT_CLASS_ENTRY_EX((*ce), cname, strlen(cname), g_funcs[cidx]); - zend_register_internal_class(ce TSRMLS_CC); - - return 0; -} - -int zend_add_method(int cidx, int fidx, int cbid, char *cname, char *mname, char *atys, int rety) -{ - printf("add mth %s::%s at %d:%d=%d, %p, atys=%s, rety=%d\n", - cname, mname, cidx, fidx, cbid, phpgo_handlers[cbid], atys, rety); - - if (phpgo_handlers[cbid] == NULL) { - assert(phpgo_handlers[cbid] != NULL); - return -1; - } - - zend_function_entry *fe = &g_funcs[cidx][fidx]; - zend_function_entry e = {strdup(mname), phpgo_handlers[cbid], NULL, 0, - 0 | ZEND_ACC_PUBLIC}; - memcpy(fe, &e, sizeof(e)); - - phpgo_argtys[cbid] = atys == NULL ? NULL : strdup(atys); - phpgo_retys[cbid] = rety; - - return 0; -} - -// TODO PHP class instance destroyed diff --git a/phpgo/extension.go b/phpgo/extension.go deleted file mode 100644 index 530164f..0000000 --- a/phpgo/extension.go +++ /dev/null @@ -1,509 +0,0 @@ -package phpgo - -/* -#include "extension.h" -#include "../zend/compat.h" - -#include -#include -#include -#include -#include -#include - -*/ -import "C" -import "unsafe" -import "reflect" -import "errors" -import "fmt" -import "log" -import "os" -import "github.com/kitech/php-go/zend" -import "strings" - -// 一个程序只能创建一个扩展 -// 所以使用全局变量也没有问题。 -var ( - ExtName string = "" - ExtVer string = "1.0" -) - -//export InitExtension -func InitExtension(name string, version string) int { - ExtName = name - if len(version) > 0 { - ExtVer = version - } - - return 0 -} - -var gext = NewExtension() - -type FuncEntry struct { - class string - method string - fn interface{} - isctor bool - isdtor bool -} - -func NewFuncEntry(class string, method string, fn interface{}) *FuncEntry { - return &FuncEntry{class, method, fn, false, false} -} - -func (this *FuncEntry) Name() string { - return this.class + "_" + this.method -} - -func (this *FuncEntry) IsGlobal() bool { - return this.class == "global" -} - -func (this *FuncEntry) IsCtor() bool { - return !this.IsGlobal() && this.isctor -} - -func (this *FuncEntry) IsDtor() bool { - return !this.IsGlobal() && this.isdtor -} - -func (this *FuncEntry) IsMethod() bool { - return !this.IsGlobal() && !this.isctor && !this.isdtor -} - -// 支持的函数类型为, -// 至少要是个函数或者方法 -// 最多只能返回一个值 -// 参数个数小于等于10 -// 返回值类型,必须是以下4类,string, intx, floatx, bool -func (this *FuncEntry) IsSupported() bool { - return true -} - -type Extension struct { - syms map[string]int - classes map[string]int - cbs map[int]*FuncEntry // cbid => callable callbak - - fidx int // = 0 - - objs map[uintptr]interface{} // php's this => go's this - objs_p map[unsafe.Pointer]interface{} // php's this => go's this - - // phpgo init function - module_startup_func func(int, int) int - module_shutdown_func func(int, int) int - request_startup_func func(int, int) int - request_shutdown_func func(int, int) int - - me *C.zend_module_entry - fe *C.zend_function_entry -} - -// 与C中的同名结构体对应 -type phpgo_callback_signature struct { - argtys [10]int8 - rety int - varidict int -} - -// TODO 把entry位置与cbid分开,这样cbfunc就能够更紧凑了 -func NewExtension() *Extension { - syms := make(map[string]int, 0) - classes := make(map[string]int, 0) - cbs := make(map[int]*FuncEntry, 0) - objs := make(map[uintptr]interface{}, 0) - objs_p := make(map[unsafe.Pointer]interface{}, 0) - - classes["global"] = 0 // 可以看作内置函数的类 - return &Extension{syms: syms, classes: classes, cbs: cbs, - objs: objs, objs_p: objs_p} -} - -// depcreated -func gencbid(cidx int, fidx int) int { - return cidx*128 + fidx -} - -func nxtcbid() int { - return len(gext.syms) -} - -func AddFunc(name string, f interface{}) error { - fe := NewFuncEntry("global", name, f) - sname := fe.Name() - - if _, has := gext.syms[sname]; !has { - // TODO check f type - - cidx := 0 - fidx := gext.fidx - // cbid := gencbid(0, fidx) - cbid := nxtcbid() - - argtys := zend.ArgTypes2Php(f) - var cargtys *C.char = nil - if argtys != nil { - cargtys = C.CString(*argtys) - } - rety := zend.RetType2Php(f) - - cname := C.CString(name) - n := C.zend_add_function(C.int(cidx), C.int(fidx), C.int(cbid), cname, cargtys, C.int(rety)) - C.free(unsafe.Pointer(cname)) - if argtys != nil { - C.free(unsafe.Pointer(cargtys)) - } - - if int(n) == 0 { - gext.syms[sname] = cbid - gext.cbs[cbid] = fe - gext.fidx += 1 - return nil - } - } - - return errors.New("add func error.") -} - -// 添加新类的时候,可以把类的公共方法全部导出吧 -// 不用逐个方法添加,简单多了。 -// @param ctor 是该类的构造函数,原型 func NewClass(...) *Class -func AddClass(name string, ctor interface{}) error { - - if _, has := gext.classes[name]; !has { - cidx := len(gext.classes) - - var n C.int = 0 - if int(n) == 0 { - addCtor(cidx, name, ctor) - addDtor(cidx, name, ctor) - addMethods(cidx, name, ctor) - } - - fmt.Println("add class:", name, cidx) - cname := C.CString(name) - n = C.zend_add_class(C.int(cidx), cname) - C.free(unsafe.Pointer(cname)) - - if int(n) == 0 { - gext.classes[name] = cidx - } - return nil - } - - return errors.New("add class error.") -} - -func addDtor(cidx int, cname string, ctor interface{}) { - mname := "__destruct" - fidx := 1 - addMethod(cidx, fidx, cname, mname, ctor, false, true) -} - -func addCtor(cidx int, cname string, ctor interface{}) { - mname := "__construct" - fidx := 0 - addMethod(cidx, fidx, cname, mname, ctor, true, false) -} - -func addMethods(cidx int, cname string, ctor interface{}) { - fty := reflect.TypeOf(ctor) - cls := fty.Out(0) - - for idx := 0; idx < cls.NumMethod(); idx++ { - mth := cls.Method(idx) - addMethod(cidx, idx+2, cname, mth.Name, mth.Func.Interface(), false, false) - } -} - -func addMethod(cidx int, fidx int, cname string, mname string, fn interface{}, isctor, isdtor bool) { - // cidx := gext.classes[cname] - // cbid := gencbid(cidx, fidx) - cbid := nxtcbid() - - fe := NewFuncEntry(cname, mname, fn) - fe.isctor = isctor - fe.isdtor = isdtor - - argtys := zend.ArgTypes2Php(fn) - var cargtys *C.char = nil - if argtys != nil { - cargtys = C.CString(*argtys) - } - rety := zend.RetType2Php(fn) - - ccname := C.CString(cname) - cmname := C.CString(mname) - - mn := C.zend_add_method(C.int(cidx), C.int(fidx), C.int(cbid), ccname, cmname, cargtys, C.int(rety)) - C.free(unsafe.Pointer(ccname)) - C.free(unsafe.Pointer(cmname)) - if argtys != nil { - C.free(unsafe.Pointer(cargtys)) - } - - if mn == 0 { - gext.cbs[cbid] = fe - gext.syms[fe.Name()] = cbid - } -} - -func validFunc(fn interface{}) bool { - fty := reflect.TypeOf(fn) - if fty.Kind() != reflect.Func { - log.Panicln("What's that?", fty.Kind().String()) - } - - if fty.IsVariadic() { - log.Panicln("Can't support variadic func.", fty.Kind().String()) - } - - for idx := 0; idx < fty.NumIn(); idx++ { - switch fty.In(idx).Kind() { - case reflect.Func: - fallthrough - case reflect.Array: - fallthrough - case reflect.Slice: - fallthrough - case reflect.Chan: - fallthrough - case reflect.Map: - fallthrough - default: - log.Panicln("Can't support arg type:", idx, fty.In(idx).Kind().String()) - } - } - - return true -} - -/* -* @param namespace string optional - */ -func AddConstant(name string, val interface{}, namespace interface{}) { - if len(name) == 0 { - return - } - - if namespace != nil { - log.Println("Warning, namespace parameter not supported now. omited.") - } - - module_number := C.phpgo_get_module_number() - modname := C.CString(strings.ToUpper(name)) - defer C.free(unsafe.Pointer(modname)) - - if val != nil { - switch v := val.(type) { - case string: - modval := C.CString(v) - defer C.free(unsafe.Pointer(modval)) - - C.zend_register_stringl_constant_compat(modname, C.size_t(len(name)), modval, C.size_t(len(v)), - C.CONST_CS|C.CONST_PERSISTENT, C.int(module_number)) - case int, int32, uint32, int64, uint64, int8, uint8: - iv := reflect.ValueOf(v).Convert(reflect.TypeOf(int64(1))).Interface() - C.zend_register_long_constant_compat(modname, C.size_t(len(name)), C.zend_long(iv.(int64)), - C.CONST_CS|C.CONST_PERSISTENT, C.int(module_number)) - case float32, float64: - fv := reflect.ValueOf(v).Convert(reflect.TypeOf(float64(1.0))).Interface() - C.zend_register_double_constant_compat(modname, C.size_t(len(name)), C.double(fv.(float64)), - C.CONST_CS|C.CONST_PERSISTENT, C.int(module_number)) - case bool: - var bv int8 = 1 - if v == false { - bv = 0 - } - C.zend_register_bool_constant_compat(modname, C.size_t(len(name)), C.zend_bool(bv), - C.CONST_CS|C.CONST_PERSISTENT, C.int(module_number)) - default: - valty := reflect.TypeOf(val) - log.Panicln("Warning, unsported constant value type:", valty.Kind().String()) - } - } else { - C.zend_register_null_constant_compat(modname, C.size_t(len(name)), - C.CONST_CS|C.CONST_PERSISTENT, C.int(module_number)) - } - -} - -// TODO 如果比较多的话,可以摘出来,放在builtin.go中 -// 内置函数注册,内置类注册。 -func addBuiltins() { - // nice fix exit crash bug. - AddFunc("GoExit", func(code int) { os.Exit(code) }) - AddFunc("GoGo", func(fn interface{}) { log.Println(fn) }) - AddFunc("GoPanic", func() { panic("got") }) - AddFunc("GoRecover", func() { recover() }) - AddFunc("GoPrintln", func(p0 int, v interface{}) { log.Println(v, 123333) }) -} - -// 注册php module 初始化函数 -func RegisterInitFunctions(module_startup_func func(int, int) int, - module_shutdown_func func(int, int) int, - request_startup_func func(int, int) int, - request_shutdown_func func(int, int) int) { - - gext.module_startup_func = module_startup_func - gext.module_shutdown_func = module_shutdown_func - gext.request_startup_func = request_startup_func - gext.request_shutdown_func = request_shutdown_func - - tocip := func(f interface{}) unsafe.Pointer { - return unsafe.Pointer(&f) - } - - C.phpgo_register_init_functions(tocip(gext.module_startup_func), tocip(gext.module_shutdown_func), - tocip(gext.request_startup_func), tocip(gext.request_shutdown_func)) -} - -// -// 以整数类型传递go值类型的实现的回调方式 -//export on_phpgo_function_callback -func on_phpgo_function_callback(cbid int, phpthis uintptr, - a0 uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, - a5 uintptr, a6 uintptr, a7 uintptr, a8 uintptr, a9 uintptr) uintptr { - - args := []uintptr{a0, a1, a2, a3, a4, a5, a6, a7, a8, a9} - if len(args) > 0 { - } - - log.Println("go callback called:", cbid, phpthis, gext.cbs[cbid]) - log.Println("go callback called:", args) - - fe := gext.cbs[cbid] - // fe.fn.(func())() - - // 根据方法原型中的参数个数与类型,从当前函数中的a0-a9中提取正确的值出来 - fval := reflect.ValueOf(fe.fn) - argv := zend.ArgValuesFromPhp(fe.fn, args) - - if fe.IsMethod() { - if phpthis == 0 { - panic("wtf") - } - if _, has := gext.objs[phpthis]; !has { - panic("wtf") - } - gothis := gext.objs[phpthis] - // argv = append([]reflect.Value{reflect.ValueOf(gothis)}, argv...) - argv[0] = reflect.ValueOf(gothis) - } - - outs := fval.Call(argv) - ret := zend.RetValue2Php(fe.fn, outs) - fmt.Println("meta call ret:", outs, ret) - - if fe.IsCtor() { - if phpthis == 0 { - panic("wtf") - } - if _, has := gext.objs[phpthis]; has { - panic("wtf") - } - gext.objs[phpthis] = outs[0].Interface() - } - - return ret -} - -// -// 以指针类型传递go值类型的实现的回调方式 -//export on_phpgo_function_callback_p -func on_phpgo_function_callback_p(cbid int, phpthis unsafe.Pointer, - a0 unsafe.Pointer, a1 unsafe.Pointer, a2 unsafe.Pointer, a3 unsafe.Pointer, a4 unsafe.Pointer, - a5 unsafe.Pointer, a6 unsafe.Pointer, a7 unsafe.Pointer, a8 unsafe.Pointer, a9 unsafe.Pointer, - retpp *unsafe.Pointer, op unsafe.Pointer) { - - args := []unsafe.Pointer{a0, a1, a2, a3, a4, a5, a6, a7, a8, a9} - if len(args) > 0 { - } - - log.Println("go callback called:", cbid, phpthis, gext.cbs[cbid], op) - log.Println("go callback called:", args) - - fe := gext.cbs[cbid] - // fe.fn.(func())() - - if op == nil && !fe.IsGlobal() { - panic("is not a class or a function") - } - - // 根据方法原型中的参数个数与类型,从当前函数中的a0-a9中提取正确的值出来 - fval := reflect.ValueOf(fe.fn) - argv := zend.ArgValuesFromPhp_p(fe.fn, args, fe.IsMethod()) - - if fe.IsMethod() { - zend.CHKNILEXIT(phpthis, "wtf") - gothis, has := gext.objs_p[op] - if !has { - panic("wtf") - } - // argv = append([]reflect.Value{reflect.ValueOf(gothis)}, argv...) - argv[0] = reflect.ValueOf(gothis) - } - - outs := fval.Call(argv) - ret := zend.RetValue2Php_p(fe.fn, outs) - log.Println("meta call ret:", outs, ret) - - if fe.IsCtor() { - zend.CHKNILEXIT(phpthis, "wtf") - if _, has := gext.objs_p[op]; has { - panic("wtf") - } - gext.objs_p[op] = outs[0].Interface() - } - - if fe.IsDtor() { - zend.CHKNILEXIT(phpthis, "wtf") - if _, has := gext.objs_p[op]; !has { - panic("wtf") - } - delete(gext.objs_p, op) - } - - *retpp = ret - // return ret -} - -// -// 比较通用的在C中调用go任意函数的方法 -// on_phpgo_function_callback是根据cbid来确定如何调用函数 -// 该函数直接根据函数指定fp函数指针对应的函数。 -//export call_golang_function -func call_golang_function(fp unsafe.Pointer, a0 uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, - a5 uintptr, a6 uintptr, a7 uintptr, a8 uintptr, a9 uintptr) uintptr { - - fval := reflect.ValueOf(*(*interface{})(fp)) - if fval.Interface() == nil { - panic("wtf") - } - - args := []uintptr{a0, a1, a2, a3, a4, a5, a6, a7, a8, a9} - if len(args) > 0 { - } - argv := zend.ArgValuesFromPhp(fval.Interface(), args) - if len(argv) > 0 { - } - - outs := fval.Call(argv) - ret := zend.RetValue2Php(fval.Interface(), outs) - - return ret -} - -// -// 比较通用的在C中调用go任意函数的方法(但参数是都指针形式的) -// 该函数直接根据函数指定fp函数指针对应的函数。 -//export call_golang_function_p -func call_golang_function_p(fp unsafe.Pointer, a0 unsafe.Pointer, a1 unsafe.Pointer, a2 unsafe.Pointer, - a3 unsafe.Pointer, a4 unsafe.Pointer, a5 unsafe.Pointer, a6 unsafe.Pointer, - a7 unsafe.Pointer, a8 unsafe.Pointer, a9 unsafe.Pointer) unsafe.Pointer { - - return nil -} diff --git a/phpgo/extension.h b/phpgo/extension.h deleted file mode 100644 index 9b74744..0000000 --- a/phpgo/extension.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _PHPGO_EXTENSION_H_ -#define _PHPGO_EXTENSION_H_ - -extern void* phpgo_get_module(char *name, char *version); -extern int phpgo_get_module_number(); -void phpgo_register_init_functions(void *module_startup_func, void *module_shutdown_func, - void *request_startup_func, void *request_shutdown_func); -extern int zend_add_function(int cidx, int fidx, int cbid, char *name, char *atys, int rety); -extern int zend_add_class(int cidx, char *name); -extern int zend_add_method(int cidx, int fidx, int cbid, char *name, char *mname, char *atys, int rety); - -#endif diff --git a/phpgo/extension_adds.txt b/phpgo/extension_adds.txt deleted file mode 100644 index 4495d2a..0000000 --- a/phpgo/extension_adds.txt +++ /dev/null @@ -1,123 +0,0 @@ -PHPGO_FH_ADD(0); -PHPGO_FH_ADD(1); -PHPGO_FH_ADD(2); -PHPGO_FH_ADD(3); -PHPGO_FH_ADD(4); -PHPGO_FH_ADD(5); -PHPGO_FH_ADD(6); -PHPGO_FH_ADD(7); -PHPGO_FH_ADD(8); -PHPGO_FH_ADD(9); -PHPGO_FH_ADD(10); -PHPGO_FH_ADD(11); -PHPGO_FH_ADD(12); -PHPGO_FH_ADD(13); -PHPGO_FH_ADD(14); -PHPGO_FH_ADD(15); -PHPGO_FH_ADD(16); -PHPGO_FH_ADD(17); -PHPGO_FH_ADD(18); -PHPGO_FH_ADD(19); -PHPGO_FH_ADD(20); -PHPGO_FH_ADD(21); -PHPGO_FH_ADD(22); -PHPGO_FH_ADD(23); -PHPGO_FH_ADD(24); -PHPGO_FH_ADD(25); -PHPGO_FH_ADD(26); -PHPGO_FH_ADD(27); -PHPGO_FH_ADD(28); -PHPGO_FH_ADD(29); -PHPGO_FH_ADD(30); -PHPGO_FH_ADD(31); -PHPGO_FH_ADD(32); -PHPGO_FH_ADD(33); -PHPGO_FH_ADD(34); -PHPGO_FH_ADD(35); -PHPGO_FH_ADD(36); -PHPGO_FH_ADD(37); -PHPGO_FH_ADD(38); -PHPGO_FH_ADD(39); -PHPGO_FH_ADD(40); -PHPGO_FH_ADD(41); -PHPGO_FH_ADD(42); -PHPGO_FH_ADD(43); -PHPGO_FH_ADD(44); -PHPGO_FH_ADD(45); -PHPGO_FH_ADD(46); -PHPGO_FH_ADD(47); -PHPGO_FH_ADD(48); -PHPGO_FH_ADD(49); -PHPGO_FH_ADD(50); -PHPGO_FH_ADD(51); -PHPGO_FH_ADD(52); -PHPGO_FH_ADD(53); -PHPGO_FH_ADD(54); -PHPGO_FH_ADD(55); -PHPGO_FH_ADD(56); -PHPGO_FH_ADD(57); -PHPGO_FH_ADD(58); -PHPGO_FH_ADD(59); -PHPGO_FH_ADD(60); -PHPGO_FH_ADD(61); -PHPGO_FH_ADD(62); -PHPGO_FH_ADD(63); -PHPGO_FH_ADD(64); -PHPGO_FH_ADD(65); -PHPGO_FH_ADD(66); -PHPGO_FH_ADD(67); -PHPGO_FH_ADD(68); -PHPGO_FH_ADD(69); -PHPGO_FH_ADD(70); -PHPGO_FH_ADD(71); -PHPGO_FH_ADD(72); -PHPGO_FH_ADD(73); -PHPGO_FH_ADD(74); -PHPGO_FH_ADD(75); -PHPGO_FH_ADD(76); -PHPGO_FH_ADD(77); -PHPGO_FH_ADD(78); -PHPGO_FH_ADD(79); -PHPGO_FH_ADD(80); -PHPGO_FH_ADD(81); -PHPGO_FH_ADD(82); -PHPGO_FH_ADD(83); -PHPGO_FH_ADD(84); -PHPGO_FH_ADD(85); -PHPGO_FH_ADD(86); -PHPGO_FH_ADD(87); -PHPGO_FH_ADD(88); -PHPGO_FH_ADD(89); -PHPGO_FH_ADD(90); -PHPGO_FH_ADD(91); -PHPGO_FH_ADD(92); -PHPGO_FH_ADD(93); -PHPGO_FH_ADD(94); -PHPGO_FH_ADD(95); -PHPGO_FH_ADD(96); -PHPGO_FH_ADD(97); -PHPGO_FH_ADD(98); -PHPGO_FH_ADD(99); -PHPGO_FH_ADD(100); -PHPGO_FH_ADD(101); -PHPGO_FH_ADD(102); -PHPGO_FH_ADD(103); -PHPGO_FH_ADD(104); -PHPGO_FH_ADD(105); -PHPGO_FH_ADD(106); -PHPGO_FH_ADD(107); -PHPGO_FH_ADD(108); -PHPGO_FH_ADD(109); -PHPGO_FH_ADD(110); -PHPGO_FH_ADD(111); -PHPGO_FH_ADD(112); -PHPGO_FH_ADD(113); -PHPGO_FH_ADD(114); -PHPGO_FH_ADD(115); -PHPGO_FH_ADD(116); -PHPGO_FH_ADD(117); -PHPGO_FH_ADD(118); -PHPGO_FH_ADD(119); -PHPGO_FH_ADD(120); -PHPGO_FH_ADD(121); -PHPGO_FH_ADD(122); diff --git a/phpgo/extension_syms.txt b/phpgo/extension_syms.txt deleted file mode 100644 index 690e54d..0000000 --- a/phpgo/extension_syms.txt +++ /dev/null @@ -1,123 +0,0 @@ -PHPGO_FH_DECL(0); -PHPGO_FH_DECL(1); -PHPGO_FH_DECL(2); -PHPGO_FH_DECL(3); -PHPGO_FH_DECL(4); -PHPGO_FH_DECL(5); -PHPGO_FH_DECL(6); -PHPGO_FH_DECL(7); -PHPGO_FH_DECL(8); -PHPGO_FH_DECL(9); -PHPGO_FH_DECL(10); -PHPGO_FH_DECL(11); -PHPGO_FH_DECL(12); -PHPGO_FH_DECL(13); -PHPGO_FH_DECL(14); -PHPGO_FH_DECL(15); -PHPGO_FH_DECL(16); -PHPGO_FH_DECL(17); -PHPGO_FH_DECL(18); -PHPGO_FH_DECL(19); -PHPGO_FH_DECL(20); -PHPGO_FH_DECL(21); -PHPGO_FH_DECL(22); -PHPGO_FH_DECL(23); -PHPGO_FH_DECL(24); -PHPGO_FH_DECL(25); -PHPGO_FH_DECL(26); -PHPGO_FH_DECL(27); -PHPGO_FH_DECL(28); -PHPGO_FH_DECL(29); -PHPGO_FH_DECL(30); -PHPGO_FH_DECL(31); -PHPGO_FH_DECL(32); -PHPGO_FH_DECL(33); -PHPGO_FH_DECL(34); -PHPGO_FH_DECL(35); -PHPGO_FH_DECL(36); -PHPGO_FH_DECL(37); -PHPGO_FH_DECL(38); -PHPGO_FH_DECL(39); -PHPGO_FH_DECL(40); -PHPGO_FH_DECL(41); -PHPGO_FH_DECL(42); -PHPGO_FH_DECL(43); -PHPGO_FH_DECL(44); -PHPGO_FH_DECL(45); -PHPGO_FH_DECL(46); -PHPGO_FH_DECL(47); -PHPGO_FH_DECL(48); -PHPGO_FH_DECL(49); -PHPGO_FH_DECL(50); -PHPGO_FH_DECL(51); -PHPGO_FH_DECL(52); -PHPGO_FH_DECL(53); -PHPGO_FH_DECL(54); -PHPGO_FH_DECL(55); -PHPGO_FH_DECL(56); -PHPGO_FH_DECL(57); -PHPGO_FH_DECL(58); -PHPGO_FH_DECL(59); -PHPGO_FH_DECL(60); -PHPGO_FH_DECL(61); -PHPGO_FH_DECL(62); -PHPGO_FH_DECL(63); -PHPGO_FH_DECL(64); -PHPGO_FH_DECL(65); -PHPGO_FH_DECL(66); -PHPGO_FH_DECL(67); -PHPGO_FH_DECL(68); -PHPGO_FH_DECL(69); -PHPGO_FH_DECL(70); -PHPGO_FH_DECL(71); -PHPGO_FH_DECL(72); -PHPGO_FH_DECL(73); -PHPGO_FH_DECL(74); -PHPGO_FH_DECL(75); -PHPGO_FH_DECL(76); -PHPGO_FH_DECL(77); -PHPGO_FH_DECL(78); -PHPGO_FH_DECL(79); -PHPGO_FH_DECL(80); -PHPGO_FH_DECL(81); -PHPGO_FH_DECL(82); -PHPGO_FH_DECL(83); -PHPGO_FH_DECL(84); -PHPGO_FH_DECL(85); -PHPGO_FH_DECL(86); -PHPGO_FH_DECL(87); -PHPGO_FH_DECL(88); -PHPGO_FH_DECL(89); -PHPGO_FH_DECL(90); -PHPGO_FH_DECL(91); -PHPGO_FH_DECL(92); -PHPGO_FH_DECL(93); -PHPGO_FH_DECL(94); -PHPGO_FH_DECL(95); -PHPGO_FH_DECL(96); -PHPGO_FH_DECL(97); -PHPGO_FH_DECL(98); -PHPGO_FH_DECL(99); -PHPGO_FH_DECL(100); -PHPGO_FH_DECL(101); -PHPGO_FH_DECL(102); -PHPGO_FH_DECL(103); -PHPGO_FH_DECL(104); -PHPGO_FH_DECL(105); -PHPGO_FH_DECL(106); -PHPGO_FH_DECL(107); -PHPGO_FH_DECL(108); -PHPGO_FH_DECL(109); -PHPGO_FH_DECL(110); -PHPGO_FH_DECL(111); -PHPGO_FH_DECL(112); -PHPGO_FH_DECL(113); -PHPGO_FH_DECL(114); -PHPGO_FH_DECL(115); -PHPGO_FH_DECL(116); -PHPGO_FH_DECL(117); -PHPGO_FH_DECL(118); -PHPGO_FH_DECL(119); -PHPGO_FH_DECL(120); -PHPGO_FH_DECL(121); -PHPGO_FH_DECL(122); diff --git a/phpgo/init.go b/phpgo/init.go deleted file mode 100644 index 80b2b21..0000000 --- a/phpgo/init.go +++ /dev/null @@ -1,28 +0,0 @@ -package phpgo - -/* -#include "extension.h" -*/ -import "C" -import "unsafe" - -// import "runtime" - -// import "os" -import "fmt" - -// -// 给php加载扩展时调用的扩展入口函数。 -//export get_module -func get_module() unsafe.Pointer { - if len(ExtName) == 0 { - panic("ext name not set.") - } - - addBuiltins() - - mod := C.phpgo_get_module(C.CString(ExtName), C.CString(ExtVer)) - fmt.Printf("mod=%p\n", mod) - - return unsafe.Pointer(mod) -} diff --git a/phpgo/phpgo.go b/phpgo/phpgo.go deleted file mode 100644 index 83e0fb2..0000000 --- a/phpgo/phpgo.go +++ /dev/null @@ -1,12 +0,0 @@ -package phpgo - -/* -// #cgo CFLAGS: -I/usr/include/php -I/usr/include/php/Zend -I/usr/include/php/TSRM -// #cgo LDFLAGS: -L/home/dev/php5/lib -lphp5 -#cgo CFLAGS: -g -O2 -std=c99 -D_GNU_SOURCE -// #cgo LDFLAGS: -lphp5 -#cgo linux LDFLAGS: -Wl,--warn-unresolved-symbols -Wl,--unresolved-symbols=ignore-all -#cgo darwin LDFLAGS: -undefined dynamic_lookup - -*/ -import "C" diff --git a/zend/compat.c b/zend/compat.c deleted file mode 100644 index 21533ba..0000000 --- a/zend/compat.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "compat.h" - -ZEND_API void zend_register_stringl_constant_compat(const char *name, size_t name_len, char *strval, size_t strlen, int flags, int module_number) -{ - zend_register_stringl_constant(name, name_len, strval, strlen, flags, module_number); -} - -ZEND_API void zend_register_long_constant_compat(const char *name, size_t name_len, zend_long lval, int flags, int module_number) -{ - zend_register_long_constant(name, name_len, lval, flags, module_number); -} - -ZEND_API void zend_register_double_constant_compat(const char *name, size_t name_len, double dval, int flags, int module_number) -{ - zend_register_double_constant(name, name_len, dval, flags, module_number); -} - -ZEND_API void zend_register_bool_constant_compat(const char *name, size_t name_len, zend_bool bval, int flags, int module_number) -{ - zend_register_bool_constant(name, name_len, bval, flags, module_number); -} - -ZEND_API void zend_register_null_constant_compat(const char *name, size_t name_len, int flags, int module_number) -{ - zend_register_null_constant(name, name_len, flags, module_number); -} - diff --git a/zend/compat.h b/zend/compat.h deleted file mode 100644 index dc29bdc..0000000 --- a/zend/compat.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef _PHP_COMPAT_H_ -#define _PHP_COMPAT_H_ - -#include -#include - -#ifdef ZEND_ENGINE_3 -#define Z_BVAL_PP(zv) Z_LVAL_P(*(zv)) -#define Z_LVAL_PP(zv) Z_LVAL_P(*(zv)) -#define Z_DVAL_PP(zv) Z_DVAL_P(*(zv)) -#define Z_STRVAL_PP(zv) Z_STRVAL_P(*(zv)) -#define Z_STRLEN_PP(zv) Z_STRLEN_P(*(zv)) -#define Z_ARRVAL_PP(zv) Z_ARRVAL_P(*(zv)) -#define Z_TYPE_PP(zv) Z_TYPE_P(*(zv)) -#endif - -#ifdef ZEND_ENGINE_2 -typedef long zend_long; -#define _IS_BOOL IS_BOOL -#define IS_TRUE (IS_CALLABLE+1) -#define IS_FALSE (IS_CALLABLE+2) -#define IS_UNDEF (IS_CALLABLE+3) - -#if !defined(IS_CONSTANT_AST) -#error "Maybe you are using not supported zend < 2.5.0 (PHP < 5.5.0)" -#endif - -#endif - -ZEND_API void zend_register_stringl_constant_compat(const char *name, size_t name_len, char *strval, size_t strlen, int flags, int module_number); -ZEND_API void zend_register_long_constant_compat(const char *name, size_t name_len, zend_long lval, int flags, int module_number); -ZEND_API void zend_register_double_constant_compat(const char *name, size_t name_len, double dval, int flags, int module_number); -ZEND_API void zend_register_bool_constant_compat(const char *name, size_t name_len, zend_bool bval, int flags, int module_number); -ZEND_API void zend_register_null_constant_compat(const char *name, size_t name_len, int flags, int module_number); - - -#endif diff --git a/zend/goapi.c b/zend/goapi.c deleted file mode 100644 index d28086e..0000000 --- a/zend/goapi.c +++ /dev/null @@ -1,2 +0,0 @@ -#include "goapi.h" - diff --git a/zend/goapi.go b/zend/goapi.go deleted file mode 100644 index a22a360..0000000 --- a/zend/goapi.go +++ /dev/null @@ -1,368 +0,0 @@ -package zend - -/* -#include -*/ -import "C" -import "reflect" -import "unsafe" -import "log" - -//// -//export goapi_array_new -func goapi_array_new(kind int, retpp *unsafe.Pointer) { - sty := FROMCIP(goapi_type_r(kind)).(reflect.Type) - log.Println(sty.Kind().String(), sty) - arrval := reflect.MakeSlice(reflect.SliceOf(sty), 0, 0) - *retpp = TOCIP(arrval.Interface()) -} - -//export goapi_array_push -func goapi_array_push(arrp unsafe.Pointer, elm unsafe.Pointer, retpp *unsafe.Pointer) { - // *arr = append(*arr, s) - arr := FROMCIP(arrp) - vty := reflect.TypeOf(arr) - if vty != nil { - } - - switch vty.Elem().Kind() { - case reflect.Int64: - elmval := (int64)(C.int64_t(uintptr(elm))) - narr := append(arr.([]int64), elmval) - *retpp = TOCIP(narr) - case reflect.String: - // only support string element - elmval := C.GoString((*C.char)(elm)) - narr := append(arr.([]string), elmval) - *retpp = TOCIP(narr) - } - return -} - -//export goapi_map_new -func goapi_map_new(retpp *unsafe.Pointer) { - // m := make(map[string]string, 0) - kty := FROMCIP(goapi_type_r(int(reflect.String))).(reflect.Type) - vty := FROMCIP(goapi_type_r(int(reflect.String))).(reflect.Type) - mv := reflect.MakeMap(reflect.MapOf(kty, vty)) - m := mv.Interface().(map[string]string) - - *retpp = TOCIP(m) -} - -//export goapi_map_add -func goapi_map_add(mp unsafe.Pointer, keyp unsafe.Pointer, valuep unsafe.Pointer) { - m := FROMCIP(mp).(map[string]string) - key := C.GoString((*C.char)(keyp)) - value := C.GoString((*C.char)(valuep)) - - m[key] = value -} - -//export goapi_map_get -func goapi_map_get(mp unsafe.Pointer, keyp unsafe.Pointer, retpp *unsafe.Pointer) { - m := FROMCIP(mp).(map[string]string) - key := C.GoString((*C.char)(keyp)) - - if _, has := m[key]; has { - v := m[key] - *retpp = unsafe.Pointer(C.CString(v)) - } - - return -} - -//export goapi_map_del -func goapi_map_del(mp unsafe.Pointer, keyp unsafe.Pointer) { - m := FROMCIP(mp).(map[string]string) - key := C.GoString((*C.char)(keyp)) - - if _, has := m[key]; has { - delete(m, key) - } -} - -//export goapi_map_has -func goapi_map_has(mp unsafe.Pointer, keyp unsafe.Pointer) bool { - m := FROMCIP(mp).(map[string]string) - key := C.GoString((*C.char)(keyp)) - - if _, has := m[key]; has { - return true - } - - return false -} - -//export goapi_chan_new -func goapi_chan_new(kind int, buffer int, retpp *unsafe.Pointer) { - cty := FROMCIP(goapi_type_r(kind)).(reflect.Type) - chval := reflect.MakeChan(cty, buffer) - - *retpp = TOCIP(chval.Interface()) -} - -// TODO -//export goapi_chan_read -func goapi_chan_read(chp unsafe.Pointer, retpp *unsafe.Pointer) { - ch := FROMCIP(chp) - chv := reflect.ValueOf(ch) - - rv, ok := chv.Recv() - if ok { - *retpp = TOCIP(rv.Interface()) - } -} - -// TODO -//export goapi_chan_write -func goapi_chan_write(chp unsafe.Pointer, elm unsafe.Pointer) { - ch := FROMCIP(chp) - chv := reflect.ValueOf(ch) - - chv.Send(reflect.ValueOf(FROMCIP(elm))) -} - -// TODO -//export goapi_chan_close -func goapi_chan_close(chp unsafe.Pointer) { - ch := FROMCIP(chp) - chv := reflect.ValueOf(ch) - - chv.Close() -} - -func goapi_type_r(kind int) unsafe.Pointer { - var retpp unsafe.Pointer - goapi_type(kind, &retpp) - return retpp -} - -//export goapi_type -func goapi_type(kind int, retpp *unsafe.Pointer) { - wkind := (reflect.Kind)(kind) - - var refty reflect.Type - - switch wkind { - case reflect.Invalid: - case reflect.Bool: - refty = reflect.TypeOf(true) - case reflect.Int: - refty = reflect.TypeOf(int(0)) - case reflect.Int8: - refty = reflect.TypeOf(int8(0)) - case reflect.Int16: - refty = reflect.TypeOf(int16(0)) - case reflect.Int32: - refty = reflect.TypeOf(int32(0)) - case reflect.Int64: - refty = reflect.TypeOf(int64(0)) - case reflect.Uint: - refty = reflect.TypeOf(uint(0)) - case reflect.Uint8: - refty = reflect.TypeOf(uint8(0)) - case reflect.Uint16: - refty = reflect.TypeOf(uint16(0)) - case reflect.Uint32: - refty = reflect.TypeOf(uint32(0)) - case reflect.Uint64: - refty = reflect.TypeOf(uint64(0)) - case reflect.Uintptr: - refty = reflect.TypeOf(uintptr(0)) - case reflect.Float32: - refty = reflect.TypeOf(float32(1.0)) - case reflect.Float64: - refty = reflect.TypeOf(float64(1.0)) - case reflect.Complex64: - case reflect.Complex128: - case reflect.Array: - refty = reflect.TypeOf([]interface{}{}) - case reflect.Chan: - case reflect.Func: - case reflect.Interface: - case reflect.Map: - refty = reflect.TypeOf(map[interface{}]interface{}{}) - case reflect.Ptr: - case reflect.Slice: - case reflect.String: - refty = reflect.TypeOf("") - case reflect.Struct: - case reflect.UnsafePointer: - refty = reflect.TypeOf(unsafe.Pointer(uintptr(0))) - } - - *retpp = TOCIP(refty) -} - -//export goapi_typeof -func goapi_typeof(v unsafe.Pointer, retpp *unsafe.Pointer) { - gv := FROMCIP(v) - *retpp = TOCIP(reflect.TypeOf(gv)) -} - -//export goapi_typeid -func goapi_typeid(v unsafe.Pointer) int { - gv := FROMCIP(v) - return int(reflect.TypeOf(gv).Kind()) -} - -//export goapi_new -func goapi_new(kind int, retpp *unsafe.Pointer) { - refty := goapi_type_r(kind) - refval := reflect.New(FROMCIP(refty).(reflect.Type)) - - *retpp = TOCIP(refval) -} -func goapi_new_kind(kind reflect.Kind, retpp *unsafe.Pointer) { - goapi_new(int(kind), retpp) -} -func goapi_new_type(kty reflect.Type, retpp *unsafe.Pointer) { - goapi_new_kind(kty.Kind(), retpp) -} - -//export goapi_new_value -func goapi_new_value(kind int, v uintptr, retpp *unsafe.Pointer) { - wkind := reflect.Kind(kind) - - var refval interface{} - switch wkind { - case reflect.Invalid: - case reflect.Bool: - if v == 0 { - refval = false - } else { - refval = true - } - case reflect.Int: - refval = int(v) - case reflect.Int8: - refval = int8(v) - case reflect.Int16: - refval = int16(v) - case reflect.Int32: - refval = int32(v) - case reflect.Int64: - refval = int64(v) - case reflect.Uint: - refval = uint(v) - case reflect.Uint8: - refval = uint8(v) - case reflect.Uint16: - refval = uint16(v) - case reflect.Uint32: - refval = uint32(v) - case reflect.Uint64: - refval = uint64(v) - case reflect.Uintptr: - refval = v - case reflect.Float32: - refval = float32(*(*C.float)(unsafe.Pointer(v))) - C.free(unsafe.Pointer(v)) - case reflect.Float64: - refval = float64(*(*C.double)(unsafe.Pointer(v))) - C.free(unsafe.Pointer(v)) - case reflect.Complex64: - case reflect.Complex128: - case reflect.Array: - case reflect.Chan: - case reflect.Func: - case reflect.Interface: - case reflect.Map: - case reflect.Ptr: - case reflect.Slice: - case reflect.String: - refval = C.GoString((*C.char)(unsafe.Pointer(v))) - case reflect.Struct: - case reflect.UnsafePointer: - refval = unsafe.Pointer(v) - } - - *retpp = TOCIP(refval) -} - -//export goapi_set_value -func goapi_set_value(gv unsafe.Pointer, v uintptr, retpp *unsafe.Pointer) { - giv := FROMCIP(gv) - gvty := reflect.TypeOf(giv) - var nv unsafe.Pointer - goapi_new_value(int(gvty.Kind()), v, &nv) - reflect.ValueOf(giv).Set(reflect.ValueOf(FROMCIP(nv))) - - if *retpp != gv { - *retpp = gv - } -} - -//export goapi_get_value -func goapi_get_value(gv unsafe.Pointer) uintptr { - giv := FROMCIP(gv) - gvty := reflect.TypeOf(giv) - if gvty == nil { - return 0 - } - - var rv uintptr - - switch gvty.Kind() { - case reflect.Invalid: - case reflect.Bool: - if giv.(bool) { - rv = 1 - } else { - rv = 0 - } - case reflect.Int: - rv = (uintptr)(giv.(int)) - case reflect.Int8: - rv = (uintptr)(giv.(int8)) - case reflect.Int16: - rv = (uintptr)(giv.(int16)) - case reflect.Int32: - rv = (uintptr)(giv.(int32)) - case reflect.Int64: - rv = (uintptr)(giv.(int64)) - case reflect.Uint: - rv = (uintptr)(giv.(uint)) - case reflect.Uint8: - rv = (uintptr)(giv.(uint8)) - case reflect.Uint16: - rv = (uintptr)(giv.(uint16)) - case reflect.Uint32: - rv = (uintptr)(giv.(uint32)) - case reflect.Uint64: - rv = (uintptr)(giv.(uint64)) - case reflect.Uintptr: - rv = giv.(uintptr) - case reflect.Float32: - case reflect.Float64: - case reflect.Complex64: - case reflect.Complex128: - case reflect.Array: - case reflect.Chan: - case reflect.Func: - case reflect.Interface: - case reflect.Map: - case reflect.Ptr: - case reflect.Slice: - case reflect.String: - rv = uintptr(unsafe.Pointer(C.CString(giv.(string)))) - case reflect.Struct: - case reflect.UnsafePointer: - rv = (uintptr)(giv.(unsafe.Pointer)) - } - - // 简洁方式 - rvty := FROMCIP(goapi_type_r(int(reflect.Uintptr))).(reflect.Type) - if gvty.ConvertibleTo(rvty) { - rv = reflect.ValueOf(giv).Convert(rvty).Interface().(uintptr) - } else { - switch gvty.Kind() { - case reflect.Ptr: - rv = reflect.ValueOf(giv).Pointer() - default: - log.Panicln("can not convert:", giv, gvty.Kind(), gvty, rvty) - } - } - return rv -} diff --git a/zend/goapi.h b/zend/goapi.h deleted file mode 100644 index d6459fd..0000000 --- a/zend/goapi.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef _GOAPI_H_ -#define _GOAPI_H_ - -#include - - -enum GoType { - GT_Invalid , - GT_Bool , - GT_Int , - GT_Int8 , - GT_Int16 , - GT_Int32 , - GT_Int64 , - GT_Uint , - GT_Uint8 , - GT_Uint16 , - GT_Uint32 , - GT_Uint64 , - GT_Uintptr , - GT_Float32 , - GT_Float64 , - GT_Complex64 , - GT_Complex128 , - GT_Array , - GT_Chan , - GT_Func , - GT_Interface , - GT_Map , - GT_Ptr , - GT_Slice , - GT_String , - GT_Struct , - GT_UnsafePointer, -}; - - -/* Start of boilerplate cgo prologue. */ - -#ifndef GO_CGO_PROLOGUE_H -#define GO_CGO_PROLOGUE_H - -typedef signed char GoInt8; -typedef unsigned char GoUint8; -typedef short GoInt16; -typedef unsigned short GoUint16; -typedef int GoInt32; -typedef unsigned int GoUint32; -typedef long long GoInt64; -typedef unsigned long long GoUint64; -typedef GoInt64 GoInt; -typedef GoUint64 GoUint; -typedef __SIZE_TYPE__ GoUintptr; -typedef float GoFloat32; -typedef double GoFloat64; -typedef __complex float GoComplex64; -typedef __complex double GoComplex128; - -// static assertion to make sure the file is being used on architecture -// at least with matching size of GoInt. -typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; - -typedef struct { char *p; GoInt n; } GoString; -typedef void *GoMap; -typedef void *GoChan; -typedef struct { void *t; void *v; } GoInterface; -typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; - -#endif - -/* End of boilerplate cgo prologue. */ - -#endif - diff --git a/zend/init.go b/zend/init.go deleted file mode 100644 index efea0f7..0000000 --- a/zend/init.go +++ /dev/null @@ -1,25 +0,0 @@ -package zend - -/* - */ -import "C" - -// import "unsafe" -import "runtime" - -import "time" -import "math/rand" - -// import "os" -import "fmt" - -// -func init() { - omp := runtime.GOMAXPROCS(1) - fmt.Println("run gozend init...", omp) - omp = runtime.GOMAXPROCS(1) - fmt.Println("run gozend init...", omp) - - rand.Seed(time.Now().UnixNano()) - -} diff --git a/zend/sphp.c b/zend/sphp.c deleted file mode 100644 index a23edba..0000000 --- a/zend/sphp.c +++ /dev/null @@ -1,10 +0,0 @@ -#include - -char* gozend_php_version() { - return PHP_VERSION; -} - -int gozend_php_version_id() { - return PHP_VERSION_ID; -} - diff --git a/zend/szend.c b/zend/szend.c deleted file mode 100644 index 21748e8..0000000 --- a/zend/szend.c +++ /dev/null @@ -1,185 +0,0 @@ - -#include -#include - -#include "sztypes.h" - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include "zend_API.h" - -#ifdef ZEND_ENGINE_3 -int gozend_call_user_function(zval *object, char *func_name, zval *retval_ptr, int argc, zval *params) -{ - zval function_name; - ZVAL_NULL(&function_name); - ZVAL_STRING(&function_name, func_name); - - assert(retval_ptr != NULL); - if (call_user_function(CG(function_table), object , &function_name, - retval_ptr, argc, params TSRMLS_CC) == SUCCESS) { - return 0; - } - return -1; -} -#else /* ZEND_ENGINE_2 */ -int gozend_call_user_function(zval **object, char *func_name, zval *retval_ptr, int argc, zval **params) -{ - zval function_name; - INIT_ZVAL(function_name); - ZVAL_STRING(&function_name, func_name, 1); - - assert(retval_ptr != NULL); - if (call_user_function(CG(function_table), object , &function_name, - retval_ptr, argc, params TSRMLS_CC) == SUCCESS) { - return 0; - } - return -1; -} -#endif - - -#ifdef ZEND_ENGINE_3 -static int gozend_call_user_function_string_ex(char *func_name, char *str, char **retstr, zval *object) -{ - zval args[9]; - ZVAL_NULL(&args[0]); - ZVAL_STRING(&args[0], str); - - zval retval_ptr; - ZVAL_NULL(&retval_ptr); - - int ret = gozend_call_user_function(object, func_name, &retval_ptr, 1, args); - if (ret == 0) { - char *cstr = NULL; - int cslen = 0; - - if (Z_TYPE_P(&retval_ptr) == IS_STRING) { - cslen = Z_STRLEN_P(&retval_ptr); - cstr = estrndup(Z_STRVAL_P(&retval_ptr), cslen); - *retstr = cstr; - } - } - return ret; -} -#else /* ZEND_ENGINE_2 */ -static int gozend_call_user_function_string_ex(char *func_name, char *str, char **retstr, zval **object) -{ - zval *args[9]; - MAKE_STD_ZVAL(args[0]); - ZVAL_STRING(args[0], str, 1); - - zval retval_ptr; - ZVAL_NULL(&retval_ptr) - - int ret = gozend_call_user_function(object, func_name, &retval_ptr, 1, args); - if (ret == 0) { - char *cstr = NULL; - int cslen = 0; - - if (Z_TYPE_P(&retval_ptr) == IS_STRING) { - cslen = Z_STRLEN_P(&retval_ptr); - cstr = estrndup(Z_STRVAL_P(&retval_ptr), cslen); - *retstr = cstr; - } - } - return ret; -} -#endif - - -char *gozend_call_user_function_string(char *func_name, char *str) -{ - char *res = NULL; - int ret = gozend_call_user_function_string_ex(func_name, str, &res, NULL); - return res; -} - -int gozend_iszts() { -#ifdef ZTS - return 1; -#else - return 0; -#endif -} - -int gozend_zend_version_no() { -#ifdef ZEND_ENGINE_3 - return 3; -#else - return 2; -#endif -} - -char* gozend_zend_version() { - return get_zend_version(); -} - -void gozend_efree(void *ptr) { - efree(ptr); -} - -char *gozend_estrdup(char *str) { - return estrdup(str); -} - -char *gozend_estrndup(char *str, unsigned int length) { - return estrndup(str, length); -} - -void *gozend_emalloc(size_t size) { - return emalloc(size); -} - -void *gozend_ecalloc(size_t nmemb, size_t size) { - return ecalloc(nmemb, size); -} - -void *gozend_erealloc(void *ptr, size_t size) { - return erealloc(ptr, size); -} - -char gozend_eval_string(char *code) -{ - zval retval; - #ifdef ZEND_ENGINE_3 - ZVAL_NULL(&retval); - #else - INIT_ZVAL(retval); - #endif - - int ret = zend_eval_string(code, &retval, (char*)"" TSRMLS_CC); - - // zval_ptr_dtor(&retval); - zval_dtor(&retval); - return ret == FAILURE; -} - - -void call_user_function_callback(char *data) -{ - uint32_t argc = 0; - zval retval_ptr; - char *func_name = "say_hello_123"; - zval function_name; -#ifdef ZEND_ENGINE_3 - ZVAL_NULL(&retval_ptr); - ZVAL_NULL(&function_name); - ZVAL_STRING(&function_name, func_name); -#else - INIT_ZVAL(retval_ptr); - INIT_ZVAL(function_name); - ZVAL_STRING(&function_name, func_name, 1); -#endif - - void *cobj = NULL; /* no object */ - if (call_user_function(CG(function_table), cobj , &function_name, - &retval_ptr, argc, NULL TSRMLS_CC) == SUCCESS) { - /* do something with retval_ptr here if you like */ - } - - /* don't forget to free the zvals */ - // zval_ptr_dtor(&retval_ptr); - zval_dtor(&function_name); -} diff --git a/zend/szend.h b/zend/szend.h deleted file mode 100644 index dc86926..0000000 --- a/zend/szend.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef _SZEND_H_ -#define _SZEND_H_ - -#include -#include - -extern char* gozend_call_user_function_string(char *func_name, char *arg); -extern void gozend_efree(void *ptr); -extern char *gozend_estrdup(char *str); -extern char *gozend_estrndup(char *str, unsigned int lenght); -extern void *gozend_emalloc(size_t size); -extern void *gozend_ecalloc(size_t nmemb, size_t size); -extern void *gozend_erealloc(void *ptr, size_t size); -extern char gozend_eval_string(char *code); -extern void call_user_function_callback(char *arg); - -#endif diff --git a/zend/sztypes.h b/zend/sztypes.h deleted file mode 100644 index c0ac169..0000000 --- a/zend/sztypes.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _SZ_TYPES_H_ -#define _SZ_TYPES_H_ - -#include - -#ifndef uint -#define uint unsigned int -#endif -#ifndef ulong -#define ulong unsigned long -#endif - -#endif - diff --git a/zend/typeconv.go b/zend/typeconv.go deleted file mode 100644 index 82438b4..0000000 --- a/zend/typeconv.go +++ /dev/null @@ -1,322 +0,0 @@ -package zend - -// go类型转换为PHP类型 - -/* -#include - -#include -#include "../zend/compat.h" -*/ -import "C" -import "unsafe" - -import ( - "log" - "reflect" -) - -const ( - PHPTY_IS_NULL = C.IS_NULL - PHPTY_IS_LONG = C.IS_LONG - PHPTY_IS_DOUBLE = C.IS_DOUBLE - PHPTY_IS_BOOL = C._IS_BOOL - PHPTY_IS_TRUE = C.IS_TRUE - PHPTY_IS_FALSE = C.IS_FALSE - PHPTY_IS_ARRAY = C.IS_ARRAY - PHPTY_IS_OBJECT = C.IS_OBJECT - PHPTY_IS_STRING = C.IS_STRING - PHPTY_IS_RESOURCE = C.IS_RESOURCE - PHPTY_IS_CONSTANT = C.IS_CONSTANT - PHPTY_IS_CONSTANT_AST = C.IS_CONSTANT_AST - PHPTY_IS_CALLABLE = C.IS_CALLABLE - - PHPTY_IS_CONSTANT_TYPE_MASK = 0x00f - PHPTY_IS_CONSTANT_UNQUALIFIED = 0x010 - PHPTY_IS_LEXICAL_VAR = 0x020 - PHPTY_IS_LEXICAL_REF = 0x040 - PHPTY_IS_CONSTANT_IN_NAMESPACE = 0x100 -) - -func ArgTypes2Php(fn interface{}) (ptfs *string) { - fty := reflect.TypeOf(fn) - if fty.Kind() != reflect.Func { - log.Panicln("What's that?", fty.Kind().String()) - } - - var tfs string - - for idx := 0; idx < fty.NumIn(); idx++ { - switch fty.In(idx).Kind() { - case reflect.String: - tfs = tfs + "s" - case reflect.Float64: - fallthrough - case reflect.Float32: - tfs = tfs + "d" - case reflect.Bool: - tfs = tfs + "b" - case reflect.Int64: - fallthrough - case reflect.Uint64: - fallthrough - case reflect.Int32: - fallthrough - case reflect.Uint32: - fallthrough - case reflect.Int: - fallthrough - case reflect.Uint: - fallthrough - case reflect.Int16: - fallthrough - case reflect.Uint16: - fallthrough - case reflect.Int8: - fallthrough - case reflect.Uint8: - tfs = tfs + "l" - case reflect.Ptr: - tfs = tfs + "p" - case reflect.Interface: - tfs = tfs + "a" // Any/interface - case reflect.Slice: - tfs = tfs + "v" // vector - case reflect.Map: - tfs = tfs + "m" - default: - log.Panicln("Unsupported kind:", "wtf", fty.In(idx).String(), - fty.In(idx).Kind(), reflect.TypeOf(fn).IsVariadic()) - } - } - log.Println("===", tfs, fty.NumIn()) - return &tfs -} - -func RetType2Php(fn interface{}) (rety int) { - fty := reflect.TypeOf(fn) - if fty.Kind() != reflect.Func { - log.Panicln("What's that?", fty.Kind().String()) - } - - if fty.NumOut() > 0 { - switch fty.Out(0).Kind() { - case reflect.String: - rety = PHPTY_IS_STRING - case reflect.Float64: - fallthrough - case reflect.Float32: - rety = PHPTY_IS_DOUBLE - case reflect.Bool: - rety = PHPTY_IS_BOOL - case reflect.Int64: - fallthrough - case reflect.Uint64: - fallthrough - case reflect.Int32: - fallthrough - case reflect.Uint32: - fallthrough - case reflect.Int: - fallthrough - case reflect.Uint: - fallthrough - case reflect.Int16: - fallthrough - case reflect.Uint16: - fallthrough - case reflect.Int8: - fallthrough - case reflect.Uint8: - rety = PHPTY_IS_LONG - case reflect.Ptr: - rety = PHPTY_IS_RESOURCE - default: - log.Panicln("wtf", fty.Out(0).String(), fty.Out(0).Kind().String()) - } - } - - return -} - -func ArgValuesFromPhp(fn interface{}, args []uintptr) (argv []reflect.Value) { - fty := reflect.TypeOf(fn) - if fty.Kind() != reflect.Func { - log.Panicln("What's that?", fty.Kind().String()) - } - - argv = make([]reflect.Value, 0) - for idx := 0; idx < fty.NumIn(); idx++ { - switch fty.In(idx).Kind() { - case reflect.String: - var arg = C.GoString((*C.char)(unsafe.Pointer(args[idx]))) - var v = reflect.ValueOf(arg).Convert(fty.In(idx)) - argv = append(argv, v) - case reflect.Float64: - fallthrough - case reflect.Float32: - var arg = (*C.double)(unsafe.Pointer(args[idx])) - var v = reflect.ValueOf(*arg).Convert(fty.In(idx)) - argv = append(argv, v) - C.free(unsafe.Pointer(args[idx])) - case reflect.Bool: - var arg = (C.int)(args[idx]) - if arg == 1 { - argv = append(argv, reflect.ValueOf(true)) - } else { - argv = append(argv, reflect.ValueOf(false)) - } - case reflect.Int64: - fallthrough - case reflect.Uint64: - fallthrough - case reflect.Int32: - fallthrough - case reflect.Uint32: - fallthrough - case reflect.Int: - fallthrough - case reflect.Uint: - fallthrough - case reflect.Int16: - fallthrough - case reflect.Uint16: - fallthrough - case reflect.Int8: - fallthrough - case reflect.Uint8: - var arg = (C.ulonglong)(args[idx]) - var v = reflect.ValueOf(arg).Convert(fty.In(idx)) - argv = append(argv, v) - case reflect.Ptr: - // 有可能是go类的this指针 - if idx == 0 { - // 这里仅是设置一个点位符号,这个gothis指针的位置 - argv = append(argv, reflect.ValueOf(0)) - } else { - // 不支持其他非this参数的指针 - panic("wtf") - } - case reflect.Interface: - log.Println("Unsupported interface kind:", - fty.In(idx).Kind().String(), fty.In(idx).String()) - default: - log.Panicln("Unsupported kind:", - fty.In(idx).Kind().String(), fty.In(idx).String()) - } - } - - if len(argv) != fty.NumIn() { - panic("wtf") - } - return -} - -func ArgValuesFromPhp_p(fn interface{}, args []unsafe.Pointer, ismth bool) (argv []reflect.Value) { - fty := reflect.TypeOf(fn) - if fty.Kind() != reflect.Func { - log.Panicln("What's that?", fty.Kind().String()) - } - - argv = make([]reflect.Value, fty.NumIn()) - - aidx := 0 - for idx := 0; idx < fty.NumIn(); idx++ { - if ismth && idx == 0 { - continue - } - - aty := fty.In(idx) - aiv := FROMCIP(args[aidx]) - if aiv != nil { - if !reflect.TypeOf(aiv).ConvertibleTo(aty) { - log.Panicln("can't convert ", reflect.TypeOf(aiv).Kind().String(), aty.Kind().String(), - aty.Elem().Kind(), reflect.TypeOf(aiv).AssignableTo(aty), reflect.TypeOf(aiv).Elem().Kind()) - } - argv[idx] = reflect.ValueOf(aiv).Convert(aty) - } else { - log.Panicln("nil arg", idx, ismth, fty.Name()) - } - - aidx += 1 - } - - if len(argv) != fty.NumIn() { - panic("wtf") - } - return -} - -// TODO 多值返回的支持? -func RetValue2Php(fn interface{}, rvs []reflect.Value) (retv uintptr) { - fty := reflect.TypeOf(fn) - if fty.Kind() != reflect.Func { - log.Panicln("What's that?", fty.Kind().String()) - } - retv = 0 - - if fty.NumOut() > 0 { - switch fty.Out(0).Kind() { - case reflect.String: - // 需要reciever 释放内存 - retv = uintptr(unsafe.Pointer(C.CString(rvs[0].Interface().(string)))) - case reflect.Float64: - fallthrough - case reflect.Float32: - // 需要reciever 释放内存 - var pdv *C.double = (*C.double)(C.malloc(8)) - *pdv = (C.double)(rvs[0].Interface().(float64)) - retv = uintptr(unsafe.Pointer(pdv)) - case reflect.Bool: - var bv = rvs[0].Interface().(bool) - if bv { - retv = uintptr(1) - } else { - retv = uintptr(0) - } - case reflect.Int64: - fallthrough - case reflect.Uint64: - fallthrough - case reflect.Int32: - fallthrough - case reflect.Uint32: - fallthrough - case reflect.Int: - fallthrough - case reflect.Uint: - fallthrough - case reflect.Int16: - fallthrough - case reflect.Uint16: - fallthrough - case reflect.Int8: - fallthrough - case reflect.Uint8: - var dty = reflect.TypeOf(uint64(0)) - var nv = rvs[0].Convert(dty).Interface().(uint64) - retv = uintptr(nv) - case reflect.Ptr: - var nv = rvs[0].Pointer() - retv = uintptr(nv) - default: - log.Panicln("Unsupported kind:", fty.Out(0).Kind().String()) - } - } - - return -} - -// TODO 多值返回的支持? -func RetValue2Php_p(fn interface{}, rvs []reflect.Value) (retv unsafe.Pointer) { - fty := reflect.TypeOf(fn) - if fty.Kind() != reflect.Func { - log.Panicln("What's that?", fty.Kind().String()) - } - - if fty.NumOut() > 0 { - rvr := rvs[0].Interface() - return TOCIP(rvr) - } - return nil -} diff --git a/zend/utils.go b/zend/utils.go deleted file mode 100644 index 1551bd7..0000000 --- a/zend/utils.go +++ /dev/null @@ -1,67 +0,0 @@ -package zend - -import "reflect" -import "unsafe" -import "log" - -func CHKNILOMIT(v interface{}) {} -func CHKNILEXIT(v interface{}, args ...interface{}) { - if v == nil { - if len(args) > 0 { - log.Panicln(args...) - } - panic(v) - } -} - -// 看来不可能实现,需要在调用处展开的 -func CHKNILRET(v interface{}) (dfn func()) { - - dfn = func() { - if r := recover(); r != nil { - } - } - - if v == nil || v.(bool) == false { - panic(nil) - } - - return -} - -// 看来不可能实现,需要在调用处展开的 -// 也许两个连用,接近实现return到上层函数的功能,还是很啰嗦。 -func RETURN_IF_DECL(v interface{}) { - if v == nil || v.(bool) == false { - panic(nil) - } -} - -// defer RETURN_IF_EXEC()() -func RETURN_IF_EXEC(v interface{}) func() { - return func() { - if r := recover(); r != nil { - } - } -} - -type Any interface{} - -func init() { - // log.SetFlags(log.Llongfile | log.LstdFlags) - log.SetFlags(log.Lshortfile | log.LstdFlags) - log.SetPrefix("[phpgo] ") -} - -func TOCIP(v interface{}) unsafe.Pointer { - return unsafe.Pointer(&v) -} - -func FROMCIP(p unsafe.Pointer) interface{} { - if p == nil { - return nil - } - - rp := (*interface{})(p) - return reflect.ValueOf(*rp).Interface() -} diff --git a/zend/zend.go b/zend/zend.go deleted file mode 100644 index 8bb8153..0000000 --- a/zend/zend.go +++ /dev/null @@ -1,59 +0,0 @@ -package zend - -// 用go封装Zend的C API函数。 - -import ( - "errors" - // "fmt" -) - -/* -// #cgo CFLAGS: -I/usr/include/php -I/usr/include/php/Zend -I/usr/include/php/TSRM -// #cgo LDFLAGS: -L/home/dev/php5/lib -lphp5 -#cgo CFLAGS: -g -O2 -std=c99 -D_GNU_SOURCE -// #cgo LDFLAGS: -lphp5 -#cgo linux LDFLAGS: -Wl,--warn-unresolved-symbols -Wl,--unresolved-symbols=ignore-all -#cgo darwin LDFLAGS: -undefined dynamic_lookup - -#include -#include "sztypes.h" -#include "szend.h" - -*/ -import "C" -import "unsafe" -import "fmt" - -////export call_user_function_string -func Call_user_function_string(func_name string, arg string) (string, error) { - cfname := C.CString(func_name) - carg := C.CString(arg) - defer C.free(unsafe.Pointer(cfname)) - defer C.free(unsafe.Pointer(carg)) - - ret := C.gozend_call_user_function_string(cfname, carg) - if ret == nil { - return "", errors.New("call error") - } - - fmt.Printf("retp: %p\n", ret) - fmt.Println("ret:", C.GoString(ret)) - defer C.gozend_efree(unsafe.Pointer(ret)) - return C.GoString(ret), nil -} - -func Call_user_function(func_name string, args ...interface{}) { - argc := len(args) - if argc > 0 { - } - - // TODO args to zval** -} - -func Eval_string(code string) bool { - ccode := C.CString(code) - defer C.free(unsafe.Pointer(ccode)) - - ret := C.gozend_eval_string(ccode) - return ret == 1 -}