CELIX-237: Added support for argument meta info (output types) and added use of this info in the export_registration
Project: http://git-wip-us.apache.org/repos/asf/celix/repo Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/62ede189 Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/62ede189 Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/62ede189 Branch: refs/heads/develop Commit: 62ede189c0e5cbc32b1a29256f3c109e8acef02c Parents: 4c4a5e9 Author: Pepijn Noltes <[email protected]> Authored: Wed Aug 12 18:16:08 2015 +0200 Committer: Pepijn Noltes <[email protected]> Committed: Wed Aug 12 18:16:08 2015 +0200 ---------------------------------------------------------------------- ...apache.celix.calc.api.Calculator2.descriptor | 6 +- .../dynamic_function_interface/dyn_function.c | 114 +++++++++++++++++-- .../dynamic_function_interface/dyn_function.h | 15 ++- .../dynamic_function_interface/dyn_type.c | 13 ++- .../tst/dyn_function_tests.cpp | 55 ++++++++- .../private/src/export_registration_dfi.c | 81 ++++++++----- 6 files changed, 238 insertions(+), 46 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/celix/blob/62ede189/remote_services/examples/calculator_service/public/include/org.apache.celix.calc.api.Calculator2.descriptor ---------------------------------------------------------------------- diff --git a/remote_services/examples/calculator_service/public/include/org.apache.celix.calc.api.Calculator2.descriptor b/remote_services/examples/calculator_service/public/include/org.apache.celix.calc.api.Calculator2.descriptor index 711df0b..52e3322 100644 --- a/remote_services/examples/calculator_service/public/include/org.apache.celix.calc.api.Calculator2.descriptor +++ b/remote_services/examples/calculator_service/public/include/org.apache.celix.calc.api.Calculator2.descriptor @@ -6,6 +6,6 @@ version=1.0.0 classname=org.example.Calculator :types :methods -add(DD)D=add(PDD*D)N -sub(DD)D=sub(PDD*D)N -sqrt(D)D=sqrt(PD*D)N +add(DD)D=add(#PDD^*D)N +sub(DD)D=sub(#PDD^*D)N +sqrt(D)D=sqrt(#PD^*D)N http://git-wip-us.apache.org/repos/asf/celix/blob/62ede189/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.c ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.c b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.c index 0e12791..8880bc7 100644 --- a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.c +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.c @@ -27,6 +27,7 @@ typedef struct _dyn_function_argument_type dyn_function_argument_type; struct _dyn_function_argument_type { int index; char *name; + int argumentType; dyn_type *type; TAILQ_ENTRY(_dyn_function_argument_type) entries; }; @@ -40,7 +41,11 @@ DFI_SETUP_LOG(dynFunction) static int dynFunction_initCif(dyn_function_type *dynFunc); static int dynFunction_parseDescriptor(dyn_function_type *dynFunc, FILE *descriptor); -static void dynFunction_ffiBind(ffi_cif *cif, void *ret, void *args[], void *userData); +static void dynFunction_ffiBind(ffi_cif *cif, void *ret, void *args[], void *userData); + +static int dynFunction_checkArgument(dyn_function_argument_type *argument); + +static void dynFunction_parseArgMeta(FILE *descriptor, int *meta); int dynFunction_parse(FILE *descriptor, struct types_head *refTypes, dyn_function_type **out) { int status = OK; @@ -67,7 +72,12 @@ int dynFunction_parse(FILE *descriptor, struct types_head *refTypes, dyn_functio if (status == 0) { *out = dynFunc; - } + } else { + if (dynFunc != NULL) { + dynFunction_destroy(dynFunc); + } + + } return status; } @@ -106,22 +116,50 @@ static int dynFunction_parseDescriptor(dyn_function_type *dynFunc, FILE *descrip int nextChar = fgetc(descriptor); int index = 0; dyn_type *type = NULL; + int argMetaInfo = DYN_FUNCTION_ARG_META_STD_TYPE; + char argName[32]; while (nextChar != ')' && status == 0) { - type = NULL; ungetc(nextChar, descriptor); - status = dynType_parse(descriptor, NULL, dynFunc->refTypes, &type); + type = NULL; + + dynFunction_parseArgMeta(descriptor, &argMetaInfo); + dyn_function_argument_type *arg = NULL; + + status = dynType_parse(descriptor, NULL, dynFunc->refTypes, &type); if (status == 0) { - dyn_function_argument_type *arg = calloc(1, sizeof(*arg)); - arg->index = index++; - arg->type = type; - arg->name = NULL; //TODO + arg = calloc(1, sizeof(*arg)); if (arg != NULL) { - TAILQ_INSERT_TAIL(&dynFunc->arguments, arg, entries); + arg->index = index; + arg->type = type; + arg->argumentType = argMetaInfo; + + snprintf(argName, 32, "arg%04i", index); + arg->name = strdup(argName); + + index += 1; } else { LOG_ERROR("Error allocating memory"); status = MEM_ERROR; } - } + } + + if (status == 0) { + status = dynFunction_checkArgument(arg); + } + + if (status == 0) { + TAILQ_INSERT_TAIL(&dynFunc->arguments, arg, entries); + } else { + if (arg != NULL) { + if (arg->name != NULL) { + free(arg->name); + } + if (arg->type != NULL) { + dynType_destroy(arg->type); + } + free(arg); + } + } nextChar = fgetc(descriptor); } @@ -132,6 +170,48 @@ static int dynFunction_parseDescriptor(dyn_function_type *dynFunc, FILE *descrip return status; } +static void dynFunction_parseArgMeta(FILE *descriptor, int *meta) { + int c = fgetc(descriptor); + + switch (c) { + case '~' : + *meta = DYN_FUNCTION_ARG_META_OUPUT_TYPE; + break; + case '^' : + *meta = DYN_FUNCTION_ARG_META_PRE_ALLOCATED_OUTPUT_TYPE; + break; + case '#' : + *meta = DYN_FUNCTION_ARG_META_HANDLE_TYPE; + break; + default : + *meta = DYN_FUNCTION_ARG_META_STD_TYPE; + ungetc(c, descriptor); + break; + } +} + +static int dynFunction_checkArgument(dyn_function_argument_type *argument) { + int status = 0; + if (argument->argumentType == DYN_FUNCTION_ARG_META_PRE_ALLOCATED_OUTPUT_TYPE) { + //expect atleast one * + if (dynType_type(argument->type) != DYN_TYPE_TYPED_POINTER) { + status = ERROR; + } + } else if (argument->argumentType == DYN_FUNCTION_ARG_META_OUPUT_TYPE) { + //expect atleast two ** + if (dynType_type(argument->type) == DYN_TYPE_TYPED_POINTER) { + dyn_type *subType = NULL; + status = dynType_typedPointer_getTypedType(argument->type, &subType); + if (status == OK && dynType_type(subType) != DYN_TYPE_TYPED_POINTER) { + status = ERROR; + } + } else { + status = ERROR; + } + } + return status; +} + static int dynFunction_initCif(dyn_function_type *dynFunc) { int status = 0; @@ -261,4 +341,18 @@ dyn_type * dynFunction_returnType(dyn_function_type *dynFunction) { return dynFunction->funcReturn; } +int dynFunction_argumentMetaInfoForIndex(dyn_function_type *dynFunc, int argumentNr) { + int argType = DYN_FUNCTION_ARG_META_UNKNOWN_TYPE; + int index = 0; + dyn_function_argument_type *entry = NULL; + TAILQ_FOREACH(entry, &dynFunc->arguments, entries) { + if (index == argumentNr) { + argType = entry->argumentType; + break; + } + index +=1; + } + return argType; +} + http://git-wip-us.apache.org/repos/asf/celix/blob/62ede189/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.h ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.h b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.h index b1abfb6..733c092 100644 --- a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.h +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_function.h @@ -10,10 +10,22 @@ /** * Uses the following schema - * (Name)([Type]*)Type + * (Name)([ArgType]*)Type + * + * ArgType = (Type|PreAllocatedOutputType|OutputType) + * PreAllocatedOutputType = ^(Type) #Note must be *(Type) + * OutputType = ~(Type) #Note must be **(Type) * e.g add(DD)D or sum({[D[D setA setB})D */ +//TODO maybe refactor to meta info flags (e.g context/handler, output, etc with a start/stop -> M(MetaType); + +#define DYN_FUNCTION_ARG_META_UNKNOWN_TYPE 0 +#define DYN_FUNCTION_ARG_META_STD_TYPE 1 +#define DYN_FUNCTION_ARG_META_PRE_ALLOCATED_OUTPUT_TYPE 2 +#define DYN_FUNCTION_ARG_META_OUPUT_TYPE 3 +#define DYN_FUNCTION_ARG_META_HANDLE_TYPE 4 + typedef struct _dyn_function_type dyn_function_type; DFI_SETUP_LOG_HEADER(dynFunction); @@ -24,6 +36,7 @@ int dynFunction_parseWithStr(const char *descriptor, struct types_head *refTypes int dynFunction_nrOfArguments(dyn_function_type *dynFunc); dyn_type *dynFunction_argumentTypeForIndex(dyn_function_type *dynFunc, int argumentNr); dyn_type * dynFunction_returnType(dyn_function_type *dynFunction); +int dynFunction_argumentMetaInfoForIndex(dyn_function_type *dynFunc, int argumentNr); void dynFunction_destroy(dyn_function_type *dynFunc); int dynFunction_call(dyn_function_type *dynFunc, void(*fn)(void), void *returnValue, void **argValues); http://git-wip-us.apache.org/repos/asf/celix/blob/62ede189/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_type.c ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_type.c b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_type.c index e47fe6d..6396d1c 100644 --- a/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_type.c +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/dyn_type.c @@ -503,6 +503,17 @@ int dynType_alloc(dyn_type *type, void **bufLoc) { void *inst = calloc(1, type->ffiType->size); if (inst != NULL) { + if (type->type == DYN_TYPE_TYPED_POINTER) { + void *ptr = NULL; + dyn_type *sub = NULL; + status = dynType_typedPointer_getTypedType(type, &sub); + if (status == OK) { + status = dynType_alloc(sub, &ptr); + if (status == OK) { + *(void **)inst = ptr; + } + } + } *bufLoc = inst; } else { status = MEM_ERROR; @@ -913,7 +924,7 @@ static void dynType_printComplex(char *name, dyn_type *type, int depth, FILE *st } dynType_printDepth(depth, stream); - printf("}\n"); + fprintf(stream, "}\n"); } else { dynType_printDepth(depth, stream); fprintf(stream, "%s: complex type ('%s'), size is %zu, alignment is %i, descriptor is '%c'.\n", name, type->name, type->ffiType->size, type->ffiType->alignment, type->descriptor); http://git-wip-us.apache.org/repos/asf/celix/blob/62ede189/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/dyn_function_tests.cpp ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/dyn_function_tests.cpp b/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/dyn_function_tests.cpp index 006897c..ab5f33e 100644 --- a/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/dyn_function_tests.cpp +++ b/remote_services/remote_service_admin_dfi/dynamic_function_interface/tst/dyn_function_tests.cpp @@ -133,6 +133,7 @@ extern "C" { static void test_example3(void) { dyn_function_type *dynFunc = NULL; + void (*fp)(void) = (void(*)(void)) testExample3; int rc; rc = dynFunction_parseWithStr(EXAMPLE3_DESCRIPTOR, NULL, &dynFunc); @@ -145,15 +146,60 @@ extern "C" { args[0] = &ptr; args[1] = &a; args[2] = &input; - void (*fp)(void) = (void(*)(void)) testExample3; - int rVal; rc = dynFunction_call(dynFunc, fp, &rVal, args); + CHECK_EQUAL(0, rc); + CHECK_EQUAL(4.0, result); + + double *inMemResult = (double *)calloc(1, sizeof(double)); + a = 2.0; + ptr = &a; + args[0] = &ptr; + args[1] = &a; + args[2] = &inMemResult; + rVal; + rc = dynFunction_call(dynFunc, fp, &rVal, args); CHECK_EQUAL(0, rc); CHECK_EQUAL(4.0, result); + free(inMemResult); + + dynFunction_destroy(dynFunc); } + void test_meta(void) { + int rc; + dyn_function_type *func = NULL; + + const char *descriptor1 = "sqrt(D^*D~**D#P)V"; + rc = dynFunction_parseWithStr(descriptor1, NULL, &func); + CHECK_EQUAL(0, rc); + CHECK_EQUAL(DYN_FUNCTION_ARG_META_STD_TYPE, dynFunction_argumentMetaInfoForIndex(func, 0)); + CHECK_EQUAL(DYN_FUNCTION_ARG_META_PRE_ALLOCATED_OUTPUT_TYPE, dynFunction_argumentMetaInfoForIndex(func, 1)); + CHECK_EQUAL(DYN_FUNCTION_ARG_META_OUPUT_TYPE, dynFunction_argumentMetaInfoForIndex(func, 2)); + CHECK_EQUAL(DYN_FUNCTION_ARG_META_HANDLE_TYPE, dynFunction_argumentMetaInfoForIndex(func, 3)); + CHECK_EQUAL(DYN_FUNCTION_ARG_META_UNKNOWN_TYPE, dynFunction_argumentMetaInfoForIndex(func, 4)); + dynFunction_destroy(func); + + const char *descriptor2 = "sqrt(D~*D)V"; + rc = dynFunction_parseWithStr(descriptor2, NULL, &func); + CHECK(rc != 0); + + const char *descriptor3 = "sqrt(D~***D)V"; + rc = dynFunction_parseWithStr(descriptor3, NULL, &func); + CHECK_EQUAL(0, rc); + dynFunction_destroy(func); + + + const char *descriptor4 = "sqrt(D^D)V"; + rc = dynFunction_parseWithStr(descriptor4, NULL, &func); + CHECK(rc != 0); + + const char *descriptor5 = "sqrt(D^***D)V"; + rc = dynFunction_parseWithStr(descriptor5, NULL, &func); + CHECK_EQUAL(0, rc); + dynFunction_destroy(func); + } } TEST_GROUP(DynFunctionTests) { @@ -176,7 +222,10 @@ TEST(DynFunctionTests, DynFuncAccTest) { test_access_functions(); } - TEST(DynFunctionTests, DynFuncTest3) { test_example3(); +} + +TEST(DynFunctionTests, DynFuncTestMeta) { + test_meta(); } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/celix/blob/62ede189/remote_services/remote_service_admin_dfi/private/src/export_registration_dfi.c ---------------------------------------------------------------------- diff --git a/remote_services/remote_service_admin_dfi/private/src/export_registration_dfi.c b/remote_services/remote_service_admin_dfi/private/src/export_registration_dfi.c index 74512d3..c763222 100644 --- a/remote_services/remote_service_admin_dfi/private/src/export_registration_dfi.c +++ b/remote_services/remote_service_admin_dfi/private/src/export_registration_dfi.c @@ -5,6 +5,7 @@ #include <dyn_interface.h> #include <json_serializer.h> #include <remote_constants.h> +#include <assert.h> #include "export_registration.h" #include "export_registration_dfi.h" @@ -129,31 +130,43 @@ celix_status_t exportRegistration_call(export_registration_pt export, char *data if (method != NULL) { + struct generic_service_layout *serv = export->service; + int nrOfArgs = dynFunction_nrOfArguments(method->dynFunc); - void *args[nrOfArgs]; //arg 0 is handle + void *args[nrOfArgs]; json_t *arguments = json_object_get(js_request, "a"); json_t *value = NULL; - int index = -1; - json_array_foreach(arguments, index, value) { - int argNr = index + 1; - if (argNr < nrOfArgs -1 ) { //note skip last argument. this is the output - dyn_type *argType = dynFunction_argumentTypeForIndex(method->dynFunc, argNr); - status = jsonSerializer_deserializeJson(argType, value, &(args[argNr])); + + int i; + int index = 0; + for (i = 0; i < nrOfArgs; i += 1) { + int metaInfo = dynFunction_argumentMetaInfoForIndex(method->dynFunc, i); + dyn_type *argType = dynFunction_argumentTypeForIndex(method->dynFunc, i); + if (metaInfo == DYN_FUNCTION_ARG_META_PRE_ALLOCATED_OUTPUT_TYPE) { + printf("setting pre alloc output for %i\n", i); + dynType_alloc(argType, &args[i]); + + } else if ( metaInfo == DYN_FUNCTION_ARG_META_OUPUT_TYPE) { + printf("setting output for %i\n", i); + args[i] = NULL; + } else if (metaInfo == DYN_FUNCTION_ARG_META_HANDLE_TYPE) { + printf("setting handle for %i\n", i); + args[i] = &serv->handle; } else { - status = CELIX_ILLEGAL_ARGUMENT; + printf("setting std for %i\n", i); + value = json_array_get(arguments, index++); + status = jsonSerializer_deserializeJson(argType, value, &(args[i])); } - if (status != 0) { + + if (status != CELIX_SUCCESS) { break; } } json_decref(js_request); - - struct generic_service_layout *serv = export->service; - args[0] = &serv->handle; - + /* //TODO assert last is output pointer (e.g. double pointer) dyn_type *lastTypePtr = dynFunction_argumentTypeForIndex(method->dynFunc, nrOfArgs-1); dyn_type *lastType = NULL; @@ -170,34 +183,46 @@ celix_status_t exportRegistration_call(export_registration_pt export, char *data dynType_alloc(lastType, &out); //TODO, NOTE only for simple types or single pointer types.. TODO check printf("out ptr is %p value is %f\n", out, *(double *)out); args[nrOfArgs-1] = &out; //NOTE for simple type no double + */ printf("args is %p %p %p\n", args[0] , args[1], args[2]); printf("args derefs is %p %p %p\n", *(void **)args[0], *(void **)args[1], *(void **)args[2]); //TODO assert return type is native int int returnVal = 0; - //printf("calling function '%s', with index %i, nrOfArgs %i and at loc %p\n", method->id, method->index, nrOfArgs, serv->methods[method->index]); dynFunction_call(method->dynFunc, serv->methods[method->index], (void *)&returnVal, args); - //printf("done calling\n"); - //printf("args is %p %p %p\n", args[0] , args[1], args[2]); - //printf("args derefs is %p %p %p\n", *(void **)args[0], *(void **)args[1], *(void **)args[2]); - //printf("out is %p and val is %f\n", out, *(double *)out); + printf("done calling\n"); + double **r = args[2]; + printf("result ptrptr is %p, result ptr %p, result is %f\n", r, *r, **r); json_t *responseJson = NULL; - //double r = 2.0; - //status = jsonSerializer_serializeJson(lastOutputType, &r /*out*/, &responseJson); - printf("out ptr is %p, value is %f\n", out, *(double *)out); - status = jsonSerializer_serializeJson(lastType, out, &responseJson); - json_t *payload = json_object(); - json_object_set_new(payload, "r", responseJson); + for (i = 0; i < nrOfArgs; i += 1) { + int metaInfo = dynFunction_argumentMetaInfoForIndex(method->dynFunc, i); + dyn_type *argType = dynFunction_argumentTypeForIndex(method->dynFunc, i); + if (metaInfo == DYN_FUNCTION_ARG_META_PRE_ALLOCATED_OUTPUT_TYPE) { + if (status == CELIX_SUCCESS) { + status = jsonSerializer_serializeJson(argType, args[i], &responseJson); + } + break; + } else if (metaInfo == DYN_FUNCTION_ARG_META_OUPUT_TYPE) { + printf("TODO\n"); + assert(false); + } + } + + if (status == CELIX_SUCCESS) { + printf("creating payload\n"); + json_t *payload = json_object(); + json_object_set_new(payload, "r", responseJson); - char *response = json_dumps(payload, JSON_DECODE_ANY); - json_decref(payload); + char *response = json_dumps(payload, JSON_DECODE_ANY); + json_decref(payload); + *responseOut = response; + *responseLength = -1; + } - *responseOut = response; - *responseLength = -1; //TODO free args (created by jsonSerializer and dynType_alloc) (dynType_free)
