You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2015/07/02 10:02:11 UTC
[2/2] celix git commit: CELIX-237: refactoring to
dynamic_function_interface. dyn_type now uses mem stream and avro descriptor
translator added
CELIX-237: refactoring to dynamic_function_interface. dyn_type now uses mem stream and avro descriptor translator added
Project: http://git-wip-us.apache.org/repos/asf/celix/repo
Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/bdeba2bc
Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/bdeba2bc
Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/bdeba2bc
Branch: refs/heads/feature/CELIX-237_rsa-ffi
Commit: bdeba2bcb6ef277ad7e809fbd482f6a6cd2ff1ce
Parents: 7f33832
Author: Pepijn Noltes <pe...@gmail.com>
Authored: Thu Jul 2 09:59:43 2015 +0200
Committer: Pepijn Noltes <pe...@gmail.com>
Committed: Thu Jul 2 09:59:43 2015 +0200
----------------------------------------------------------------------
remote_services/CMakeLists.txt | 2 +-
remote_services/dyn_type/CMakeLists.txt | 23 -
remote_services/dyn_type/closure_tests.c | 98 ---
remote_services/dyn_type/dyn_function.c | 209 -----
remote_services/dyn_type/dyn_function.h | 24 -
remote_services/dyn_type/dyn_type.c | 535 ------------
remote_services/dyn_type/dyn_type.h | 104 ---
remote_services/dyn_type/func_tests.c | 66 --
remote_services/dyn_type/json_serializer.c | 123 ---
remote_services/dyn_type/json_serializer.h | 9 -
remote_services/dyn_type/struct_tests.c | 159 ----
.../dynamic_function_interface/CMakeLists.txt | 40 +
.../avro_descriptor_translator.c | 294 +++++++
.../descriptor_translator.h | 28 +
.../dynamic_function_interface/dfi_log_util.h | 50 ++
.../dynamic_function_interface/dyn_function.c | 185 +++++
.../dynamic_function_interface/dyn_function.h | 30 +
.../dynamic_function_interface/dyn_type.c | 822 +++++++++++++++++++
.../dynamic_function_interface/dyn_type.h | 137 ++++
.../json_serializer.c | 151 ++++
.../json_serializer.h | 12 +
.../schemas/complex.avdl | 11 +
.../schemas/complex.avpr | 36 +
.../schemas/simple.avdl | 6 +
.../schemas/simple.avpr | 33 +
.../schemas/simple_min.avpr | 1 +
.../tst/avro_descriptor_translator_tests.cpp | 67 ++
.../tst/dyn_closure_tests.cpp | 139 ++++
.../tst/dyn_function_tests.cpp | 109 +++
.../tst/dyn_type_tests.cpp | 183 +++++
.../tst/json_serializer_tests.cpp | 182 ++++
.../tst/run_tests.cpp | 9 +
32 files changed, 2526 insertions(+), 1351 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/CMakeLists.txt b/remote_services/CMakeLists.txt
index 9f56b58..b7dc13c 100644
--- a/remote_services/CMakeLists.txt
+++ b/remote_services/CMakeLists.txt
@@ -42,7 +42,7 @@ if (REMOTE_SERVICE_ADMIN)
add_subdirectory(discovery_etcd)
#add_subdirectory(discovery_shm)
- add_subdirectory(dyn_type)
+ add_subdirectory(dynamic_function_interface)
endif (REMOTE_SERVICE_ADMIN)
http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dyn_type/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/dyn_type/CMakeLists.txt b/remote_services/dyn_type/CMakeLists.txt
deleted file mode 100644
index 351bb7c..0000000
--- a/remote_services/dyn_type/CMakeLists.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-find_package(Jansson REQUIRED)
-
-add_executable(struct_tests
- struct_tests.c
- dyn_type.c
- json_serializer.c
-)
-
-add_executable(func_tests
- func_tests.c
- dyn_type.c
- dyn_function.c
-)
-
-add_executable(closure_tests
- closure_tests.c
- dyn_type.c
- dyn_function.c
-)
-
-target_link_libraries(struct_tests ${JANSSON_LIBRARIES} /lib64/libffi.so )
-target_link_libraries(func_tests ${JANSSON_LIBRARIES} /lib64/libffi.so )
-target_link_libraries(closure_tests ${JANSSON_LIBRARIES} /lib64/libffi.so )
http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dyn_type/closure_tests.c
----------------------------------------------------------------------
diff --git a/remote_services/dyn_type/closure_tests.c b/remote_services/dyn_type/closure_tests.c
deleted file mode 100644
index 39e4ca5..0000000
--- a/remote_services/dyn_type/closure_tests.c
+++ /dev/null
@@ -1,98 +0,0 @@
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "dyn_function.h"
-
-#define EXAMPLE1_SCHEMA "example(III)I"
-void example1_binding(void *userData, void* args[], void *out) {
- printf("example1 closure called\n");
- int32_t a = *((int32_t *)args[0]);
- int32_t b = *((int32_t *)args[1]);
- int32_t c = *((int32_t *)args[2]);
- int32_t *ret = out;
- *ret = a + b + c;
-}
-
-#define EXAMPLE2_SCHEMA "example(I{DDD val1 val2 val3}I)D"
-struct example2_arg2 {
- double val1;
- double val2;
- double val3;
-};
-void example2_binding(void *userData, void* args[], void *out) {
- printf("example2 closure called\n");
- int32_t a = *((int32_t *)args[0]);
- struct example2_arg2 *b = *((struct example2_arg2 **)args[1]);
- int32_t c = *((int32_t *)args[2]);
- int32_t *ret = out;
- *ret = a + b->val1 + b->val2 + b->val3 + c;
-}
-
-
-#define EXAMPLE3_SCHEMA "example(III){III sum max min}"
-struct example3_ret {
- int32_t sum;
- int32_t max;
- int32_t min;
-};
-
-void example3_binding(void *userData, void* args[], void *out) {
- printf("exampleelosure called\n");
- int32_t a = *((int32_t *)args[0]);
- int32_t b = *((int32_t *)args[1]);
- int32_t c = *((int32_t *)args[2]);
- struct example3_ret *result = calloc(1,sizeof(*result));
- result->sum = a + b + c;
- result->min = a <= b ? a : b;
- result->max = a >= b ? a : b;
- result->min = result->min <= c ? result->min : c;
- result->max = result->max >= c ? result->max : c;
-
- struct example3_ret **ret = out;
- (*ret) = result;
-}
-
-int main() {
- dyn_closure_type *dynClosure = NULL;
- int rc;
-
- rc = dynClosure_create(EXAMPLE1_SCHEMA, example1_binding, NULL, &dynClosure);
- if (rc == 0) {
- int32_t (*func)(int32_t a, int32_t b, int32_t c) = NULL;
- dynClosure_getFnPointer(dynClosure, (void *)&func);
- int32_t ret = func(2,3,4);
- printf("Return value for example1 is %i\n", ret);
- dynClosure_destroy(dynClosure);
- } else {
- printf("example1 failed\n");
- }
-
- dynClosure = NULL;
- rc = dynClosure_create(EXAMPLE2_SCHEMA, example2_binding, NULL, &dynClosure);
- if (rc == 0) {
- double (*func)(int32_t a, struct example2_arg2 *b, int32_t c) = NULL;
- dynClosure_getFnPointer(dynClosure, (void *)&func);
- struct example2_arg2 b = { .val1 = 1.0, .val2 = 1.5, .val3 = 2.0 };
- double ret = func(2,&b,4);
- printf("Return value for example2 is %f\n", ret);
- dynClosure_destroy(dynClosure);
- } else {
- printf("example2 failed\n");
- }
-
- dynClosure = NULL;
- rc = dynClosure_create(EXAMPLE3_SCHEMA, example3_binding, NULL, &dynClosure);
- if (rc == 0) {
- struct example3_ret * (*func)(int32_t a, int32_t b, int32_t c) = NULL;
- dynClosure_getFnPointer(dynClosure, (void *)&func);
- struct example3_ret *ret = func(2,8,4);
- printf("Return value for example3 is {sum:%i, max:%i, min:%i}\n", ret->sum, ret->max, ret->min);
- dynClosure_destroy(dynClosure);
- free(ret);
- } else {
- printf("example2 failed\n");
- }
-}
http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dyn_type/dyn_function.c
----------------------------------------------------------------------
diff --git a/remote_services/dyn_type/dyn_function.c b/remote_services/dyn_type/dyn_function.c
deleted file mode 100644
index a90bc64..0000000
--- a/remote_services/dyn_type/dyn_function.c
+++ /dev/null
@@ -1,209 +0,0 @@
-#include "dyn_function.h"
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <strings.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include <ffi.h>
-
-#include "dyn_type.h"
-
-struct _dyn_function_type {
- dyn_type *arguments;
- dyn_type *funcReturn;
- void (*fn)(void);
- ffi_cif cif;
-};
-
-struct _dyn_closure_type {
- dyn_type *arguments;
- dyn_type *funcReturn;
- ffi_cif cif;
- ffi_closure *ffiClosure;
- void (*fn)(void);
- void (*bind)(void *userData, void *args[], void *ret);
- void *userData;
-};
-
-
-static int dynFunction_initCif(ffi_cif *cif, dyn_type *arguments, dyn_type *funcReturn);
-static int dynFunction_parseSchema(const char *schema, dyn_type **arguments, dyn_type **funcReturn);
-static void dynClosure_ffiBind(ffi_cif *cif, void *ret, void *args[], void *userData);
-
-int dynFunction_create(const char *schema, void (*fn)(void), dyn_function_type **out) {
- int status = 0;
- dyn_function_type *dynFunc = NULL;
-
- dynFunc = calloc(1, sizeof(*dynFunc));
-
- if (dynFunc != NULL) {
- dynFunc->fn = fn;
- status = dynFunction_parseSchema(schema, &dynFunc->arguments, &dynFunc->funcReturn);
- if (status == 0) {
- status = dynFunction_initCif(&dynFunc->cif, dynFunc->arguments, dynFunc->funcReturn);
- }
- } else {
- status = 2;
- }
-
- if (status == 0) {
- *out = dynFunc;
- } else {
- if (status == 1) {
- printf("Cannot parse func schema '%s'\n", schema);
- } else {
- printf("Cannot allocate memory for dyn function\n");
- }
- }
- return status;
-}
-
-static int dynFunction_parseSchema(const char *schema, dyn_type **arguments, dyn_type **funcReturn) {
- int status = 0;
- //FIXME white space parsing is missing. Note move parsing to lex/bison?
- //TODO move to parse schema function
- char *startPos = index(schema, '(');
- char *endPos = index(schema, ')');
-
- if (startPos != NULL && endPos != NULL) {
- int nrOfArgs = 0;
- int len = endPos - startPos - 1;
-
- char *pos = startPos + 1;
- while (*pos != ')') {
- nrOfArgs += 1;
- if (*pos == '{') { //embedded struct
- while (*pos != '}' && *pos != '\0') {
- pos += 1;
- }
- }
- pos += 1;
- }
-
- printf("nrOfAgrs is %i\n", nrOfArgs);
-
- //length needed is len args +2 -> {DD}
- //+ 7 per arg e.g. {DD arg001 arg002}
- //+ 1 x \0
- //--> len args + 3 + 7 * nrArgs
- int argLength = 3 + len + 7 * nrOfArgs;
-
- char argSchema[argLength];
- argSchema[0] = '{';
- memcpy(argSchema + 1, startPos + 1, len);
- pos += len + 1;
- int i;
- for (i = 0 ; i < nrOfArgs; i += 1) {
- sprintf(argSchema + 1 + len + 7 * i, " arg%03d", i);
- pos += 7;
- }
- argSchema[argLength -2] = '}';
- argSchema[argLength -1] = '\0';
- printf("arg schema is '%s'\n", argSchema);
-
- size_t returnLen = strlen(endPos + 1);
- char returnSchema[returnLen + 1];
- memcpy(returnSchema, endPos +1, returnLen);
- returnSchema[returnLen] = '\0';
- printf("return schema is '%s'\n", returnSchema);
-
- status = dynType_create(argSchema, arguments);
- if (status == 0) {
- status = dynType_create(returnSchema, funcReturn);
- }
- } else {
- status = 1;
- }
-
- return status;
-}
-
-static int dynFunction_initCif(ffi_cif *cif, dyn_type *arguments, dyn_type *returnValue) {
- int result = 0;
-
- int count = 0;
- int i;
- for (i = 0; arguments->complex.ffiType.elements[i] != NULL; i += 1) {
- count += 1;
- }
-
- ffi_type **args = arguments->complex.ffiType.elements;
- ffi_type *returnType = &ffi_type_pointer;
- if (returnType->type == DYN_TYPE_SIMPLE) {
- returnType = returnValue->simple.ffiType;
- }
-
-
- int ffiResult = ffi_prep_cif(cif, FFI_DEFAULT_ABI, count, returnType, args);
- if (ffiResult != FFI_OK) {
- result = 1;
- }
-
- return result;
-}
-
-int dynFunction_destroy(dyn_function_type *dynFunc) {
- int result = 0;
- printf("TODO destroy dyn dync\n");
- return result;
-}
-
-int dynFunction_call(dyn_function_type *dynFunc, void *returnValue, void **argValues) {
- ffi_call(&dynFunc->cif, dynFunc->fn, returnValue, argValues);
- return 0;
-}
-
-static void dynClosure_ffiBind(ffi_cif *cif, void *ret, void *args[], void *userData) {
- dyn_closure_type *dynClosure = userData;
- dynClosure->bind(dynClosure->userData, args, ret);
-}
-
-int dynClosure_create(const char *schema, void (*bind)(void *, void **, void*), void *userData, dyn_closure_type **out) {
- int status = 0;
- dyn_closure_type *dynClosure = calloc(1, sizeof(*dynClosure));
- if (dynClosure != NULL) {
- dynClosure->bind = bind;
- dynClosure->userData = userData;
- status = dynFunction_parseSchema(schema, &dynClosure->arguments, &dynClosure->funcReturn);
- if (status == 0) {
- status = dynFunction_initCif(&dynClosure->cif, dynClosure->arguments, dynClosure->funcReturn);
- if (status == 0) {
- dynClosure->ffiClosure = ffi_closure_alloc(sizeof(ffi_closure), (void **)&dynClosure->fn);
- if (dynClosure->ffiClosure != NULL) {
- int rc = ffi_prep_closure_loc(dynClosure->ffiClosure, &dynClosure->cif, dynClosure_ffiBind, dynClosure, dynClosure->fn);
- if (rc != FFI_OK) {
- status = 1;
- }
- } else {
- status = 2;
- }
- }
- }
- } else {
- status = 2;
- }
-
- if (status == 0) {
- *out = dynClosure;
- }
- return status;
-}
-
-int dynClosure_getFnPointer(dyn_closure_type *dynClosure, void (**fn)(void)) {
- int status = 0;
- if (dynClosure != NULL) {
- (*fn) = dynClosure->fn;
- } else {
- status = 1;
- }
- return status;
-}
-
-
-int dynClosure_destroy(dyn_closure_type *dynClosure) {
- int result = 0;
- printf("TODO destroy closure\n");
- return result;
-}
http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dyn_type/dyn_function.h
----------------------------------------------------------------------
diff --git a/remote_services/dyn_type/dyn_function.h b/remote_services/dyn_type/dyn_function.h
deleted file mode 100644
index 21a5e0d..0000000
--- a/remote_services/dyn_type/dyn_function.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef __DYN_FUNCTION_H_
-#define __DYN_FUNCTION_H_
-
-#include <ffi.h>
-#include "dyn_type.h"
-
-/**
- * Uses the following schema
- * (Name)([Type]*)Type
- * e.g add(DD)D or sum({[D[D setA setB})D
- */
-
-typedef struct _dyn_function_type dyn_function_type;
-typedef struct _dyn_closure_type dyn_closure_type;
-
-int dynFunction_create(const char *schema, void (*fn)(void), dyn_function_type **dynFunc);
-int dynFunction_destroy(dyn_function_type *dynFunc);
-int dynFunction_call(dyn_function_type *dynFunc, void *returnValue, void **argValues);
-
-int dynClosure_create(const char *schema, void (*bind)(void *, void **, void*), void *userData, dyn_closure_type **out);
-int dynClosure_getFnPointer(dyn_closure_type *dynClosure, void(**fn)(void));
-int dynClosure_destroy(dyn_closure_type *dynClosure);
-
-#endif
http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dyn_type/dyn_type.c
----------------------------------------------------------------------
diff --git a/remote_services/dyn_type/dyn_type.c b/remote_services/dyn_type/dyn_type.c
deleted file mode 100644
index e7a2645..0000000
--- a/remote_services/dyn_type/dyn_type.c
+++ /dev/null
@@ -1,535 +0,0 @@
-#include "dyn_type.h"
-
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdbool.h>
-#include <assert.h>
-
-
-//place in dyn_type.h?
-struct generic_sequence {
- uint32_t _cap;
- uint32_t _len;
- void *buf;
-};
-
-
-static char dynType_schemaType(dyn_type *dynType, ffi_type *ffiType);
-
-static void dynType_print_sequence(dyn_type *type, int depth);
-static void dynType_print_complex(dyn_type *type, int depth);
-static void dynType_print_any(dyn_type *type, int depth);
-
-static unsigned short get_offset_at(ffi_type *type, int index);
-static void dynType_trim(const char *str, size_t len, int *start, int *end);
-
-static int dynType_complex_create(char *schema, dyn_type **result);
-static int dynType_sequence_create(char *schema, dyn_type **result);
-static int dynType_simple_create(char t, dyn_type **result);
-
-static ffi_type* dynType_ffiType_for(char c);
-
-int dynType_create(const char *schema, dyn_type **result) {
- //trim white space
- int status = 0;
- int offset, len;
- dynType_trim(schema, strlen(schema), &offset, &len);
-
- /*
- char test[len+1];
- memcpy(test, schema + offset, len);
- test[len] = '\0';
- printf("trimmed schema is %s\n", test);
- */
-
- if (schema[offset] == '{' && schema[offset + len -1] == '}') {
- //complex
-
- //removing prefix { and postfix }
- offset += 1;
- len -= 2;
-
- int offsetType;
- int lenType;
- //trim again
- dynType_trim(schema + offset, len , &offsetType, &lenType);
-
- char type[lenType + 1];
- memcpy(type, schema + offset + offsetType, lenType);
- type[lenType] = '\0';
- status = dynType_complex_create(type, result);
- } else if (schema[offset] == '[') {
- //sequence
- //fixme assuming simple type
- offset += 1; //remove [
- len -= 1;
- char type[len + 1];
- memcpy(type, schema + offset, len);
- type[len] = '\0';
- status = dynType_sequence_create(type, result);
- } else if (len == 1){
- //simple
- status = dynType_simple_create(schema[offset], result);
- } else {
- printf("invalid schema '%s'\n", schema);
- }
-
- return status;
-}
-
-static int dynType_simple_create(char t, dyn_type **result) {
- int status = 0;
- ffi_type *ffiType = dynType_ffiType_for(t);
- dyn_type *simple = NULL;
- if (ffiType != NULL) {
- simple = calloc(1,sizeof(*simple));
- simple->type = DYN_TYPE_SIMPLE;
- simple->simple.ffiType = ffiType;
- }
- if (ffiType != NULL && simple != NULL) {
- *result = simple;
- } else {
- printf("Error creating simple dyn type for '%c'\n", t);
- status = 1;
- }
- return status;
-}
-
-static int dynType_sequence_create(char *schema, dyn_type **result) {
- int status = 0;
- dyn_type *type = calloc(1, sizeof(*type));
-
- type->type = DYN_TYPE_SEQUENCE;
- type->sequence.seqStruct.elements = calloc(4, sizeof(ffi_type));
- type->sequence.seqStruct.elements[0] = &ffi_type_uint32; //_cap
- type->sequence.seqStruct.elements[1] = &ffi_type_uint32; //_len
- type->sequence.seqStruct.elements[2] = &ffi_type_pointer;
- type->sequence.seqStruct.elements[3] = NULL;
-
- if (schema[0] == '{') { //complex type
- int len = strlen(schema) -2;
- char complexSchema[len + 1];
- memcpy(complexSchema, schema + 1, len);
- complexSchema[len] = '\0';
- status = dynType_complex_create(complexSchema, &type->sequence.dynType);
- } else { //simple type
- type->sequence.simpleType = dynType_ffiType_for(schema[0]);
- }
- //TODO sequence of sequence
-
- if (status == 0) {
- //dummy cif prep to ensure size for struct ffi_type is set
- ffi_cif cif;
- ffi_type *args[1];
- args[0] = &type->sequence.seqStruct;
- ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_uint, args);
-
- *result = type;
- return 0;
- } else {
- printf("DYN_TYPE: invalid type schema\n");
- return 1;
- }
-
- return status;
-}
-
-static int dynType_complex_create(char *schema, dyn_type **result) {
- bool valid = true;
- size_t len = strlen(schema);
- int i = 0;
-
- dyn_type *type = calloc(1, sizeof(*type));
- type->type = DYN_TYPE_COMPLEX;
- if (type == NULL) {
- return -1;
- }
-
- //count elements
- int k;
- size_t count = 0;
- for (k=i; k < len && !isspace(schema[k]); k += 1) {
- if (schema[k] == '[') {
- k += 1;
- } else if (schema[k] == '{') {
- for (; schema[k] != '}'; k += 1) ;
- }
- count += 1;
- }
-
- type->complex.ffiType.elements = calloc(count + 1, sizeof(ffi_type));
- type->complex.nested_types = calloc(count + 1, sizeof(dyn_type *));
- int index = 0;
- for (k=0; k+i < len && !isspace(schema[k+i]); k += 1, index += 1) {
- if (schema[k+i] == '[') { //sequence
- //FIXME assume simple type
- dyn_type *seqType;
- char seq[2];
- seq[0] = schema[k+i+1];
- seq[1] = '\0';
- dynType_sequence_create(seq, &seqType);
-
- type->complex.nested_types[index] = seqType;
- type->complex.ffiType.elements[index] = &seqType->sequence.seqStruct;
- k += 1;
- } else if (schema[k+i] == '{') { //nested complex
- int start = k+i;
- int end;
- for (; schema[k+i] != '}' && k+i < len; k +=1) ;
- if (schema[k+i] == '}') {
- end = k+i;
- size_t len = end-start + 1 -2; //without {}
- char nested[len+1];
- memcpy(nested, schema + start + 1, len);
- nested[len] = '\0';
- dyn_type *nestedType = NULL;
- //TODO catch nested problem
- dynType_complex_create(nested, &nestedType); //TODO use status result
- type->complex.nested_types[index] = nestedType;
- type->complex.ffiType.elements[index] = &ffi_type_pointer;
- } else {
- printf("invalid schema. object not closed '%s'\n", schema);
- }
- } else {
- ffi_type *elType = NULL;
- elType = dynType_ffiType_for(schema[k+i]);
- if (elType != NULL) {
- type->complex.ffiType.elements[index] = elType;
- } else {
- valid=false;
- }
- }
- }
-
-
- //eat { and }
- int j;
- int nrOfBraces = 0;
- for (j = 0; j < len; j += 1) { //TODO make safer
- if (isspace(schema[j]) && nrOfBraces == 0) {
- break;
- }
- if (schema[j] == '{') {
- nrOfBraces += 1;
- } else if (schema[j] == '}') {
- nrOfBraces -=1 ;
- }
- }
-
- char *names = schema + j +1;
-
- type->complex.names = calloc(count, sizeof(char *));
- k = 0;
- char *savePtr;
- char *token = NULL;
- token = strtok_r(names, " ", &savePtr);
- while (token != NULL && k < count) {
- type->complex.names[k] = strdup(token);
- k += 1;
- token = strtok_r(NULL, " ", &savePtr);
- }
- if ( k != count || token != NULL) {
- valid =false;
- }
-
- if (valid) {
- //dummy cif prep to ensure size for struct ffi_type is set
- ffi_cif cif;
- ffi_type *args[1];
- args[0] = &type->complex.ffiType;
- ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_uint, args);
-
- *result = type;
- return 0;
- } else {
- printf("DYN_TYPE: invalid type schema '%s'\n", schema);
- return 1;
- }
-}
-
-int dynType_destroy(dyn_type *type) {
- //TODO
- return 0;
-}
-
-void * dynType_alloc(dyn_type *type) {
- assert(type != NULL);
- void *result = NULL;
- switch(type->type) {
- case DYN_TYPE_COMPLEX :
- result = calloc(1, type->complex.ffiType.size);
- break;
- case DYN_TYPE_SEQUENCE :
- result = calloc(1, type->sequence.seqStruct.size);
- break;
- case DYN_TYPE_SIMPLE :
- result = calloc(1, type->simple.ffiType->size);
- break;
- default :
- printf("DYN_TYPE: unsupported type %i\n", type->type);
- break;
- }
- return result;
-}
-
-static ffi_type* dynType_ffiType_for(char c) {
- ffi_type *type = NULL;
- switch (c) {
- case 'F' :
- type = &ffi_type_float;
- break;
- case 'D' :
- type = &ffi_type_double;
- break;
- case 'B' :
- type = &ffi_type_sint8;
- break;
- case 'S' :
- type = &ffi_type_sint16;
- break;
- case 'I' :
- type = &ffi_type_sint32;
- break;
- case 'J' :
- type = &ffi_type_sint64;
- break;
- default:
- printf("unsupported type %c\n", c);
- }
- return type;
-}
-
-static unsigned short get_offset_at(ffi_type *type, int index) {
- unsigned short offset = 0;
-
- int i;
- for (i = 0; i <= index && type->elements[i] != NULL; i += 1) {
- size_t size = type->elements[i]->size;
- unsigned short alignment = type->elements[i]->alignment;
- int alignment_diff = offset % alignment;
- if (alignment_diff > 0) {
- offset += (alignment - alignment_diff);
- }
- if (i < index) {
- offset += size;
- }
- }
-
- //TODO check if last element is not reached
-
- return offset;
-}
-
-int dynType_complex_set_value_at(dyn_type *type, int index, void *start, void *in) {
- assert(type->type == DYN_TYPE_COMPLEX);
- char *loc = ((char *)start) + get_offset_at(&type->complex.ffiType, index);
- size_t size = type->complex.ffiType.elements[index]->size;
- memcpy(loc, in, size);
- return 0;
-}
-
-int dynType_complex_index_for_name(dyn_type *type, const char *name) {
- assert(type->type == DYN_TYPE_COMPLEX);
- int i;
- int index = -1;
- for (i = 0; type->complex.ffiType.elements[i] != NULL; i += 1) {
- if (strcmp(type->complex.names[i], name) == 0) {
- index = i;
- break;
- }
- }
- return index;
-}
-
-char dynType_complex_schemaType_at(dyn_type *complexType, int index) {
- assert(complexType->type == DYN_TYPE_COMPLEX);
-
- ffi_type *type = complexType->complex.ffiType.elements[index];
- dyn_type *nestedType = complexType->complex.nested_types[index];
-
- return dynType_schemaType(nestedType, type);
-}
-
-static char dynType_schemaType(dyn_type *dynType, ffi_type *ffiType) {
- char result = '\0';
- if (dynType != NULL) {
- switch(dynType->type) {
- case DYN_TYPE_SIMPLE :
- result = dynType_schemaType(NULL, dynType->simple.ffiType);
- break;
- case DYN_TYPE_COMPLEX :
- result = '{';
- break;
- case DYN_TYPE_SEQUENCE :
- result = '[';
- break;
- }
- } else if (ffiType != NULL) {
- switch(ffiType->type) {
- case FFI_TYPE_FLOAT :
- result = 'F';
- break;
- case FFI_TYPE_DOUBLE :
- result = 'D';
- break;
- case FFI_TYPE_SINT8 :
- result = 'B';
- break;
- case FFI_TYPE_SINT16 :
- result = 'S';
- break;
- case FFI_TYPE_SINT32 :
- result = 'I';
- break;
- case FFI_TYPE_SINT64 :
- result = 'J';
- break;
- default :
- printf("Unsurported ffi type encounted. ffi type is %u\n", ffiType->type);
- }
- }
- return result;
-}
-
-dyn_type * dynType_complex_dynType_at(dyn_type *type, int index) {
- assert(type->type == DYN_TYPE_COMPLEX);
- return type->complex.nested_types[index];
-}
-
-void * dynType_complex_val_loc_at(dyn_type *type, void *inst_loc, int index) {
- assert(type->type == DYN_TYPE_COMPLEX);
- char *l = inst_loc;
- return (void *)(l + get_offset_at(&type->complex.ffiType, index));
-}
-
-int dynType_simple_set_value(dyn_type *type, void *typeLoc, void *in) {
- //TODO
- return 0;
-}
-
-static void dynType_print_sequence(dyn_type *type, int depth) {
- assert(type->type == DYN_TYPE_SEQUENCE);
- static const char const *SEQ_NAMES[] = {"_cap", "_len", "buf"};
-
- int i;
- for (i = 0; i < 3 ; i += 1) {
- int k;
- for (k = 0; k < depth; k += 1) {
- printf("\t");
- }
- printf("element %i with name '%s': size is %zu, allignment is %i and offset is %i\n", i,
- SEQ_NAMES[i], type->sequence.seqStruct.elements[i]->size, type->sequence.seqStruct.elements[i]->alignment, get_offset_at(&type->sequence.seqStruct, i));
- }
-}
-
-static void dynType_print_complex(dyn_type *type, int depth) {
- assert(type->type == DYN_TYPE_COMPLEX);
- int i, k;
- for (k = 0; k < depth; k += 1) {
- printf("\t");
- }
- printf("printing ffi type. size is %zu, allignment is %i :\n", type->complex.ffiType.size, type->complex.ffiType.alignment);
- for (i = 0; type->complex.ffiType.elements[i] != NULL; i += 1) {
- for (k = 0; k < depth; k += 1) {
- printf("\t");
- }
- printf(" element %i with name '%s': size is %zu, allignment is %i and offset is %i\n", i,
- type->complex.names[i], type->complex.ffiType.elements[i]->size, type->complex.ffiType.elements[i]->alignment, get_offset_at(&type->complex.ffiType, i));
- if (type->complex.nested_types[i] != NULL) {
- dynType_print_any(type->complex.nested_types[i], depth + 1);
- }
- }
-}
-
-static void dynType_print_any(dyn_type *type, int depth) {
- switch (type->type) {
- case DYN_TYPE_COMPLEX :
- dynType_print_complex(type, depth);
- break;
- case DYN_TYPE_SEQUENCE :
- dynType_print_sequence(type, depth);
- break;
- default :
- printf("Unsurported dyn type %i\n", type->type);
- }
-}
-
-void dynType_print(dyn_type *type) {
- dynType_print_any(type, 0);
-}
-
-size_t dynType_size(dyn_type *type) {
- assert(type != NULL);
- size_t size = 0;
- switch (type->type) {
- case DYN_TYPE_COMPLEX :
- size = type->complex.ffiType.size;
- break;
- case DYN_TYPE_SEQUENCE :
- size = type->sequence.seqStruct.size;
- break;
- case DYN_TYPE_SIMPLE :
- size = type->simple.ffiType->size;
- break;
- default :
- printf("Error unsupported type %i\n", type->type);
- break;
- }
- return size;
-}
-
-int dynType_type(dyn_type *type) {
- return type->type;
-}
-
-static void dynType_trim(const char *str, size_t strLen, int *offset, int *len) {
- int i;
- for (i = 0; i < strLen && isspace(str[i]); i += 1) {
- ;
- }
- *offset = i;
-
- for (i = strLen-1; i >= 0 && isspace(str[i]); i -= 1) {
- ;
- }
- *len = i - (*offset) + 1;
-}
-
-
-void* dynType_sequence_init(dyn_type *type, void *inst, size_t cap) {
- assert(type->type == DYN_TYPE_SEQUENCE);
- char *result;
- struct generic_sequence *seq = inst;
- if (seq != NULL) {
- size_t size = type->sequence.simpleType != NULL ? type->sequence.simpleType->size : dynType_size(type->sequence.dynType);
- seq->buf = calloc(cap, size);
- seq->_cap = cap;
- result = seq->buf;
- }
- return result;
-}
-
-char dynType_sequence_elementSchemaType(dyn_type *type) {
- assert(type->type == DYN_TYPE_SEQUENCE);
- return dynType_schemaType(type->sequence.dynType, type->sequence.simpleType);
-}
-
-int dynType_sequence_append(dyn_type *type, void *inst, void *in) {
- int index = -1;
- struct generic_sequence *seq = inst;
- if (seq->_len + 1 <= seq->_cap) {
- index = seq->_len;
- seq->_len += 1;
- char *buf = seq->buf;
- size_t elSize = type->sequence.dynType != NULL ? dynType_size(type->sequence.dynType) : type->sequence.simpleType->size;
- size_t offset = (elSize * index);
- memcpy(buf + offset, in, elSize);
- } else {
- printf("DYN_TYPE: sequence out of capacity\n");
- //todo resize ?
- }
- return index;
-}
http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dyn_type/dyn_type.h
----------------------------------------------------------------------
diff --git a/remote_services/dyn_type/dyn_type.h b/remote_services/dyn_type/dyn_type.h
deleted file mode 100644
index c7fabc5..0000000
--- a/remote_services/dyn_type/dyn_type.h
+++ /dev/null
@@ -1,104 +0,0 @@
-#ifndef __DYN_TYPE_H_
-#define __DYN_TYPE_H_
-
-#include <ffi.h>
-
-
-/*Schema description
- *
- * Type = SimpleType | ComplexType | ArrayType
- * Name = alpha[(alpha|numeric)*]
- * SPACE = ' '
- *
- * SimplesTypes (based on java bytecode method signatures)
- * //Java based:
- * B char
- * C (not supported)
- * D double
- * F float
- * I int //TODO use int32_t instead?
- * J long //TODO use int64_t intead?
- * S short //TODO use int16_t instead?
- * V void
- * Z boolean
- * //Extended
- * b unsigned char
- * i unsigned int (see I)
- * j unsigned long (see J)
- * s unsigned short (see S)
- * P pointer
- * T char* string
- *
- *
- * ComplexTypes
- * {[Type]+ [(Name)(SPACE)]+}
- *
- * NOTE MAYBE SUPPORT STRUCT BY VALUE ->
- * <[Type]+ [(Name)(SPACE)]+>
- *
- * SequenceType
- * [(Type)
- *
- * examples
- * "{DDII a b c d}" -> struct { double a; double b; int c; int d; };
- * "{DD{FF c1 c2} a b c" -> struct { double a; double b; struct c { float c1; float c2; }; };
- *
- *
- */
-
-#define DYN_TYPE_SIMPLE 1
-#define DYN_TYPE_COMPLEX 2
-#define DYN_TYPE_SEQUENCE 3
-
-typedef struct _dyn_type dyn_type;
-
-/* TODO MOVE TO PRIVATE HEADER */
-struct _dyn_type {
- int type;
- union {
- struct {
- ffi_type *ffiType;
- } simple;
-
- struct {
- ffi_type ffiType;
- char **names;
- dyn_type **nested_types;
- } complex;
-
- struct {
- ffi_type seqStruct;
- dyn_type *dynType; //set if sequence is of a complex type
- ffi_type *simpleType; //set if sequence is of a simple type
- } sequence;
- };
-};
-
-
-int dynType_create(const char *schema, dyn_type **type);
-int dynType_destroy(dyn_type *type);
-
-//generic
-void dynType_print(dyn_type *type);
-size_t dynType_size(dyn_type *type);
-int dynType_type(dyn_type *type);
-void * dynType_alloc(dyn_type *type);
-//TODO void dynType_free(dyn_type *type, void *inst);
-
-//complex
-int dynType_complex_index_for_name(dyn_type *type, const char *name);
-char dynType_complex_schemaType_at(dyn_type *type, int index);
-dyn_type * dynType_complex_dynType_at(dyn_type *type, int index);
-void * dynType_complex_val_loc_at(dyn_type *type, void *inst_loc, int index);
-int dynType_complex_set_value_at(dyn_type *type, int index, void *start_loc_type, void *in);
-
-//sequence
-void * dynType_sequence_init(dyn_type *type, void *seqInst, size_t cap); //note assume seq struct at seqLoc. only allocates buf
-char dynType_sequence_elementSchemaType(dyn_type *type);
-int dynType_sequence_append(dyn_type *type, void *inst, void *in);
-
-//simple
-int dynType_simple_set_value(dyn_type *type, void *typeLoc, void *in);
-
-
-#endif
http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dyn_type/func_tests.c
----------------------------------------------------------------------
diff --git a/remote_services/dyn_type/func_tests.c b/remote_services/dyn_type/func_tests.c
deleted file mode 100644
index 95811d7..0000000
--- a/remote_services/dyn_type/func_tests.c
+++ /dev/null
@@ -1,66 +0,0 @@
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "dyn_function.h"
-
-#define EXAMPLE1_SCHEMA "example(III)I"
-int32_t example1(int32_t a, int32_t b, int32_t c) {
- printf("example1 called with a:%i, b:%i, c:%i\n", a, b, c);
- return 1;
-}
-
-#define EXAMPLE2_SCHEMA "example(I{IID val1 val2 val3}D)D"
-struct example2_arg {
- int32_t val1;
- int32_t val2;
- double val3;
-};
-
-double example2(int32_t arg1, struct example2_arg *arg2, double arg3) {
- printf("example2 called with arg1:%i, arg2:{val1:%i, val2:%i, val3:%f}, arg3:%f\n", arg1, arg2->val1, arg2->val2, arg2->val3, arg3);
- return 2.2;
-}
-
-
-int main() {
- dyn_function_type *dynFunc = NULL;
- int rc;
-
- rc = dynFunction_create(EXAMPLE1_SCHEMA, (void *)example1, &dynFunc);
- if (rc == 0 ) {
- int32_t a = 2;
- int32_t b = 4;
- int32_t c = 8;
- void *values[3];
- int32_t rVal = 0;
- values[0] = &a;
- values[1] = &b;
- values[2] = &c;
- dynFunction_call(dynFunc, &rVal, values);
- dynFunction_destroy(dynFunc);
- dynFunc = NULL;
- } else {
- printf("Example 1 failed\n");
- }
-
- rc = dynFunction_create(EXAMPLE2_SCHEMA, (void *)example2, &dynFunc);
- if (rc == 0 ) {
- int32_t arg1 = 2;
- struct example2_arg complexVal = { .val1 = 2, .val2 = 3, .val3 = 4.1 };
- struct example2_arg *arg2 = &complexVal;
- double arg3 = 8.1;
- double returnVal = 0;
- void *values[3];
- values[0] = &arg1;
- values[1] = &arg2;
- values[2] = &arg3;
- dynFunction_call(dynFunc, &returnVal, values);
- dynFunction_destroy(dynFunc);
- dynFunc = NULL;
- } else {
- printf("Example 3 failed\n");
- }
-}
http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dyn_type/json_serializer.c
----------------------------------------------------------------------
diff --git a/remote_services/dyn_type/json_serializer.c b/remote_services/dyn_type/json_serializer.c
deleted file mode 100644
index e198445..0000000
--- a/remote_services/dyn_type/json_serializer.c
+++ /dev/null
@@ -1,123 +0,0 @@
-#include "json_serializer.h"
-
-#include <jansson.h>
-#include <assert.h>
-
-static int json_serializer_writeObject(dyn_type *type, json_t *object, void **result);
-static void json_serializer_writeObjectMember(dyn_type *type, const char *name, json_t *val, void *inst);
-static void json_serializer_writeSequence(json_t *array, dyn_type *seq, void *seqLoc);
-
-int json_deserialize(dyn_type *type, const char *input, void **result) {
- //FIXME function is assuming complex type
- int status = 0;
-
-
- json_error_t error;
- json_t *root = json_loads(input, JSON_DECODE_ANY, &error);
-
- if (root != NULL) {
- status = json_serializer_writeObject(type, root, result);
- json_decref(root);
- } else {
- status = 1;
- printf("JSON_SERIALIZER: error parsing json input '%s'. Error is %s\n", input, error.text);
- }
-
- return status;
-}
-
-static int json_serializer_writeObject(dyn_type *type, json_t *object, void **result) {
- assert(object != NULL);
- int status = 0;
-
- void *inst = dynType_alloc(type);
- json_t *value;
- const char *key;
-
- if (inst != NULL) {
- json_object_foreach(object, key, value) {
- json_serializer_writeObjectMember(type, key, value, inst);
- }
- *result = inst;
- } else {
- status = 1;
- printf("JSON_SERIALIZER: Error allocating memory\n");
- }
-
- return status;
-}
-
-static void json_serializer_writeObjectMember(dyn_type *type, const char *name, json_t *val, void *inst) {
- //TODO rename to complex. write generic write
- int index = dynType_complex_index_for_name(type, name);
- char charType = dynType_complex_schemaType_at(type, index);
- void *valp = dynType_complex_val_loc_at(type, inst, index);
-
-
- float *f;
- double *d;
- char *c;
- short *s;
- int *i;
- long *l;
- dyn_type *nested;
-
- switch (charType) {
- case 'F' :
- f = valp;
- *f = json_real_value(val);
- break;
- case 'D' :
- d = valp;
- *d = json_real_value(val);
- break;
- case 'B' :
- c = valp;
- *c = json_integer_value(val);
- break;
- case 'S' :
- s = valp;
- *s = json_integer_value(val);
- break;
- case 'I' :
- i = valp;
- *i = json_integer_value(val);
- break;
- case 'J' :
- l = valp;
- *l = json_integer_value(val);
- break;
- case '[' :
- nested = dynType_complex_dynType_at(type, index);
- json_serializer_writeSequence(val, nested, valp);
- break;
- case '{' :
- nested = dynType_complex_dynType_at(type, index);
- json_serializer_writeObject(nested, val, (void **)valp);
- break;
- default :
- printf("JSON_SERIALIZER: error provided type '%c' not supported\n", charType);
- printf("Skipping\n");
- }
-}
-
-static void json_serializer_writeSequence(json_t *array, dyn_type *seq, void *seqLoc) {
- assert(dynType_type(seq) == DYN_TYPE_SEQUENCE);
- size_t size = json_array_size(array);
- //char seqType = dynType_sequence_elementSchemaType(seq);
-
- dynType_sequence_init(seq, seqLoc, size); //seq is already allocated. only need to allocate the buf
-
- //assuming int
- int32_t i;
- int index;
- json_t *val;
- json_array_foreach(array, index, val) {
- i = json_number_value(val);
- dynType_sequence_append(seq, seqLoc, &i);
- }
-}
-
-int json_serialize(dyn_type *type, void *input, char **output, size_t *size) {
- return 0;
-}
http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dyn_type/json_serializer.h
----------------------------------------------------------------------
diff --git a/remote_services/dyn_type/json_serializer.h b/remote_services/dyn_type/json_serializer.h
deleted file mode 100644
index edc87af..0000000
--- a/remote_services/dyn_type/json_serializer.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __JSON_SERIALIZER_H_
-#define __JSON_SERIALIZER_H_
-
-#include "dyn_type.h"
-
-int json_deserialize(dyn_type *type, const char *input, void **result);
-int json_serialize(dyn_type *type, void *input, char **output, size_t *size);
-
-#endif
http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dyn_type/struct_tests.c
----------------------------------------------------------------------
diff --git a/remote_services/dyn_type/struct_tests.c b/remote_services/dyn_type/struct_tests.c
deleted file mode 100644
index ecf1fd4..0000000
--- a/remote_services/dyn_type/struct_tests.c
+++ /dev/null
@@ -1,159 +0,0 @@
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include <ffi.h>
-
-#include "dyn_type.h"
-#include "json_serializer.h"
-
-/*********** example 1 ************************/
-/** struct type ******************************/
-const char *example1_schema = "{DJISF a b c d e}";
-
-const char *example1_input = "{ \
- \"a\" : 1.0, \
- \"b\" : 22, \
- \"c\" : 32, \
- \"d\" : 42, \
- \"e\" : 4.4 \
-}";
-
-struct example1 {
- double a; //0
- int64_t b; //1
- int32_t c; //2
- int16_t d; //3
- float e; //4
-};
-
-void print_example1(void *data) {
- struct example1 *ex = data;
- printf("example1: a:%f, b:%li, c:%i, d:%i, e:%f\n", ex->a, ex->b, ex->c, ex->d, ex->e);
-}
-
-/*********** example 2 ************************/
-/** struct type with some extra whitespace*/
-const char *example2_schema = " { BJJDFD byte long1 long2 double1 float1 double2 } ";
-
-const char *example2_input = "{ \
- \"byte\" : 42, \
- \"long1\" : 232, \
- \"long2\" : 242, \
- \"double1\" : 4.2, \
- \"float1\" : 3.2, \
- \"double2\" : 4.4 \
-}";
-
-struct example2 {
- char byte; //0
- int64_t long1; //1
- int64_t long2; //2
- double double1; //3
- float float1; //4
- double double2; //5
-};
-
-void print_example2(void *data) {
- struct example2 *ex = data;
- printf("example2: byte:%i, long1:%li, long2:%li, double1:%f, float1:%f, double2:%f\n", ex->byte, ex->long1, ex->long2, ex->double1, ex->float1, ex->double2);
-}
-
-
-/*********** example 3 ************************/
-/** sequence with a simple type **************/
-const char *example3_schema = "{[I numbers}";
-
-const char *example3_input = "{ \
- \"numbers\" : [22,32,42] \
-}";
-
-struct example3 {
- struct {
- uint32_t _cap;
- uint32_t _len;
- int32_t *buf;
- } numbers;
-};
-
-void print_example3(void *data) {
- struct example3 *ex = data;
- printf("example3: numbers length is %u and cap is %u and pointer buf is %p\n", ex->numbers._len, ex->numbers._cap, ex->numbers.buf);
- int i;
- for (i = 0; i < ex->numbers._len; i += 1) {
- printf("\telement %i : %i\n", i, ex->numbers.buf[i]);
- }
-}
-
-/*********** example 4 ************************/
-/** structs within a struct (by reference)*******/
-//TODO think about references in schema e.g "{Lleaf;Lleaf; left right}\nleaf{IDD index val1 val2}"
-const char *example4_schema = "{{IDD index val1 val2}{IDD index val1 val2} left right}";
-
-const char *example4_input = "{ \
- \"left\" : {\"index\":1, \"val1\":1.0, \"val2\":2.0 }, \
- \"right\" : {\"index\":2, \"val1\":5.0, \"val2\":4.0 } \
-}";
-
-struct leaf {
- int32_t index;
- double val1;
- double val2;
-};
-
-struct example4 {
- struct leaf *left;
- struct leaf *right;
-};
-
-void print_example4(void *data) {
- struct example4 *ex = data;
- printf("example4: left { index:%i, val1:%f, val2:%f }, right { index;%i, val1:%f, val2:%f }\n", ex->left->index, ex->left->val1, ex->left->val2, ex->right->index, ex->right->val1, ex->right->val2);
-}
-
-int main() {
- printf("Starting ffi struct test\n");
- dyn_type *type;
- void *inst;
-
- type = NULL;
- inst = NULL;
- dynType_create(example1_schema, &type);
- printf("-- example 1\n");
- dynType_print(type);
- json_deserialize(type, example1_input, &inst);
- print_example1(inst);
- printf("--\n\n");
-
-
- type = NULL;
- inst = NULL;
- dynType_create(example2_schema, &type);
- printf("-- example 2\n");
- dynType_print(type);
- json_deserialize(type, example2_input, &inst);
- print_example2(inst);
- printf("--\n\n");
-
- type = NULL;
- inst = NULL;
- dynType_create(example3_schema, &type);
- printf("-- example 3\n");
- dynType_print(type);
- json_deserialize(type, example3_input, &inst);
- print_example3(inst);
- printf("--\n\n");
-
- type = NULL;
- inst = NULL;
- dynType_create(example4_schema, &type);
- printf("-- example 4\n");
- dynType_print(type);
- json_deserialize(type, example4_input, &inst);
- print_example4(inst);
- printf("--\n\n");
-
- return 0;
-}
http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/CMakeLists.txt b/remote_services/dynamic_function_interface/CMakeLists.txt
new file mode 100644
index 0000000..81e935e
--- /dev/null
+++ b/remote_services/dynamic_function_interface/CMakeLists.txt
@@ -0,0 +1,40 @@
+#
+# Licensed under Apache License v2. See LICENSE for more information.
+#
+find_package(Jansson REQUIRED)
+find_package(CppUTest REQUIRED)
+set(FFI_LIB /lib64/libffi.so) #TODO add findPackag for lib ffi
+
+include_directories(
+ ${CPPUTEST_INCLUDE_DIR}
+ ${JANSSON_INCLUDE_DIRS}
+ ${CMAKE_CURRENT_LIST_DIR}
+)
+
+add_library(dfi
+ dyn_type.c
+ dyn_function.c
+ json_serializer.c
+ avro_descriptor_translator.c
+)
+target_link_libraries(dfi ${FFI_LIB} ${JANSSON_LIBRARY})
+
+
+add_executable(dfi_tests
+ tst/dyn_type_tests.cpp
+ tst/dyn_function_tests.cpp
+ tst/dyn_closure_tests.cpp
+ tst/json_serializer_tests.cpp
+ tst/avro_descriptor_translator_tests.cpp
+ tst/run_tests.cpp
+)
+target_link_libraries(dfi_tests dfi ${FFI_LIB} ${CPPUTEST_LIBRARY} ${JANSSON_LIBRARY})
+
+add_custom_target(copy-input
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/schemas schemas
+)
+add_dependencies(dfi_tests copy-input)
+
+ADD_TARGET_FOR_TEST(dfi_tests)
+SETUP_TARGET_FOR_COVERAGE(dfi_tests_cov dfi_tests ${CMAKE_BINARY_DIR}/coverage/dfi)
+
http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/avro_descriptor_translator.c
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/avro_descriptor_translator.c b/remote_services/dynamic_function_interface/avro_descriptor_translator.c
new file mode 100644
index 0000000..9d52926
--- /dev/null
+++ b/remote_services/dynamic_function_interface/avro_descriptor_translator.c
@@ -0,0 +1,294 @@
+/**
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#include "descriptor_translator.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <jansson.h>
+
+static const int OK = 0;
+static const int MEM_ERROR = 1;
+static const int PARSE_ERROR = 2;
+static const int INV_ARG_ERROR = 2;
+
+static int descriptorTranslator_createMethodDescriptor(interface_descriptor_type *desc, json_t *schema, const char *name, int index, json_t *message);
+static int descriptorTranslator_parseMessage(json_t *schema, const char *name, json_t *message, bool asJavaSignature, char **descriptor);
+static int descriptorTranslator_parseArgument(FILE *stream, json_t *schema, json_t *type);
+static int descriptorTranslator_parseType(FILE *stream, json_t *schema, const char *typeName);
+
+int descriptorTranslator_create(const char *schemaStr, interface_descriptor_type **out) {
+ int status = OK;
+
+ interface_descriptor_type *desc = calloc(1, sizeof(*desc));
+ if (desc != NULL) {
+ TAILQ_INIT(&desc->methodDescriptors);
+ json_error_t error;
+ json_t *schema = json_loads(schemaStr, JSON_DECODE_ANY, &error);
+
+ if (schema != NULL) {
+ //TODO
+ json_t *messages = json_object_get(schema, "messages");
+ if (messages != NULL) {
+ const char *name;
+ json_t *message;
+ int rc = 0;
+ int index = 0;
+ json_object_foreach(messages, name, message) {
+ rc = descriptorTranslator_createMethodDescriptor(desc, schema, name, index++, message);
+ if (rc != OK) {
+ break;
+ }
+ }
+ }
+ //json_decref(schema);
+ } else {
+ status = PARSE_ERROR;
+ printf("AVRO_DESCRIPTOR_TRANSLATOR: error parsing json input '%s'. Error is %s\n", schemaStr, error.text);
+ }
+ } else {
+ status = MEM_ERROR;
+ }
+
+
+ if (status == 0) {
+ *out = desc;
+ } else if (status == MEM_ERROR) {
+ printf("AVRO_DESCRIPTOR_TRANSLATOR: error cannot allocate memory\n");
+ descriptorTranslator_destroy(desc);
+ } else {
+ descriptorTranslator_destroy(desc);
+ }
+ return status;
+}
+
+int descriptorTranslator_destroy(interface_descriptor_type *desc) {
+ int status = OK;
+ if (desc != NULL) {
+ //TODO free existing members
+ free(desc);
+ } else {
+ status = INV_ARG_ERROR;
+ }
+ return status;
+}
+
+static int descriptorTranslator_createMethodDescriptor(interface_descriptor_type *desc, json_t *schema, const char *name, int index, json_t *message) {
+ int status = OK;
+
+ method_descriptor_type *mDesc = calloc(1, sizeof(*mDesc));
+ if (mDesc != NULL) {
+ mDesc->identifier = index;
+ status = descriptorTranslator_parseMessage(schema, name, message, false, &mDesc->descriptor);
+ if (status == OK) {
+ mDesc->name = strdup(name);
+ if (mDesc->name == NULL) {
+ status = MEM_ERROR;
+ } else {
+ status = descriptorTranslator_parseMessage(schema, name, message, true, &mDesc->strIdentifier);
+ }
+ }
+ } else {
+ status = MEM_ERROR;
+ }
+
+ if (status == OK) {
+ TAILQ_INSERT_TAIL(&desc->methodDescriptors, mDesc, entries);
+ } else {
+ if (mDesc != NULL) {
+ if (mDesc->name != NULL) {
+ free(mDesc->name);
+ }
+ if (mDesc->descriptor != NULL) {
+ free(mDesc->descriptor);
+ }
+ if (mDesc->strIdentifier != NULL) {
+ free(mDesc->strIdentifier);
+ }
+ free(mDesc);
+ }
+ }
+
+ return status;
+}
+
+static int descriptorTranslator_parseMessage(json_t *schema, const char *name, json_t *message, bool asJavaSignature, char **descriptor) {
+ int status = OK;
+ //message -> { "request" : [ {"name":"<name>", "type":"<type>"} * ], "response":"<type>" }
+ //array -> "type":"array", "items:"<type>"
+
+ char *ptr = NULL;
+ size_t ptrSize;
+ FILE *memStream = open_memstream(&ptr, &ptrSize);
+
+ if (memStream != NULL) {
+ json_t *request = json_object_get(message, "request");
+ fwrite(name, 1, strlen(name), memStream);
+ fputc('(', memStream);
+ if (!asJavaSignature) {
+ fputc('P', memStream); //handle
+ }
+
+ if (request != NULL) {
+ size_t index;
+ json_t *arg;
+ json_array_foreach(request, index, arg) {
+ //json_t *name = json_object_get(arg, "name");
+ json_t *type = json_object_get(arg, "type");
+ if (type != NULL) {
+ status = descriptorTranslator_parseArgument(memStream, schema, type);
+ } else {
+ printf("expected type for request argument %zu for message %s\n", index, name);
+ status = PARSE_ERROR;
+ }
+ if (status != OK) {
+ break;
+ }
+ }
+ } else {
+ status = PARSE_ERROR;
+ printf("Expected request for message %s\n", name);
+ }
+
+ json_t *response = json_object_get(message, "response");
+ if (status == OK && response != NULL) {
+ if (asJavaSignature) {
+ fputc(')', memStream);
+ } else {
+ fputc('*', memStream); //output parameter
+ }
+ status = descriptorTranslator_parseArgument(memStream, schema, response);
+ }
+
+ if (!asJavaSignature) {
+ fputc(')', memStream);
+ fputc('N', memStream); //error / exceptions
+ }
+ } else {
+ status = MEM_ERROR;
+ }
+
+ if (memStream != NULL) {
+ fclose(memStream);
+ if (status == OK) {
+ *descriptor = ptr;
+ } else {
+ free(ptr);
+ }
+ }
+
+ return status;
+}
+
+static const char * const PRIMITIVE_INT = "int";
+static const char * const PRIMITIVE_LONG = "long";
+static const char * const PRIMITIVE_STRING = "string";
+static const char * const PRIMITIVE_BOOL = "boolean";
+static const char * const PRIMITIVE_FLOAT = "float";
+static const char * const PRIMITIVE_DOUBLE = "double";
+static const char * const PRIMITIVE_NULL = "null";
+static const char * const PRIMITIVE_BYTES = "bytes";
+
+static int descriptorTranslator_parseArgument(FILE *stream, json_t *schema, json_t *type) {
+ int status = OK;
+ if (json_is_string(type)) {
+ const char *typeStr = json_string_value(type);
+ char t = '\0';
+ if (strcmp(typeStr, PRIMITIVE_INT) == 0) {
+ t = 'I';
+ } else if (strcmp(typeStr, PRIMITIVE_LONG) == 0) {
+ t = 'J';
+ } else if (strcmp(typeStr, PRIMITIVE_STRING) == 0) {
+ t = 'T';
+ } else if (strcmp(typeStr, PRIMITIVE_BOOL) == 0) {
+ t = 'Z';
+ } else if (strcmp(typeStr, PRIMITIVE_FLOAT) == 0) {
+ t = 'F';
+ } else if (strcmp(typeStr, PRIMITIVE_DOUBLE) == 0) {
+ t = 'D';
+ } else if (strcmp(typeStr, PRIMITIVE_NULL) == 0) {
+ t = 'V';
+ } else if (strcmp(typeStr, PRIMITIVE_BYTES) == 0) {
+ t = 'B';
+ } else {
+ status = descriptorTranslator_parseType(stream, schema, typeStr);
+ }
+ if (t != '\0') {
+ fputc(t, stream);
+ }
+ } else {
+ json_t *subType = json_object_get(type, "type");
+ json_t *items = json_object_get(type, "items");
+ if (strcmp("array", json_string_value(subType)) == 0) {
+ //array
+ fputc('[', stream);
+ descriptorTranslator_parseArgument(stream, schema, items);
+ } else {
+ printf("sub type %s not supported\n", json_string_value(subType));
+ status = PARSE_ERROR;
+ }
+ }
+ return status;
+}
+
+
+static int descriptorTranslator_parseType(FILE *stream, json_t *schema, const char *typeName) {
+ int status = OK;
+
+ json_t *types = json_object_get(schema, "types");
+ json_t *type = NULL;
+ if (json_is_array(types)) {
+ json_t *el;
+ int index;
+ json_array_foreach(types, index, el) {
+ const char *name = json_string_value(json_object_get(el, "name"));
+ if (strcmp(typeName, name) == 0) {
+ type = el;
+ break;
+ }
+ }
+
+ if (el != NULL) {
+ fputc('{', stream);
+ json_t *fields = json_object_get(type, "fields");
+ if (json_is_array(fields)) {
+ json_t *field;
+ json_array_foreach(fields, index, field) {
+ json_t *type = json_object_get(field, "type");
+ status = descriptorTranslator_parseArgument(stream, schema, type);
+ if (status != OK) {
+ break;
+ }
+ }
+ if (status == OK) {
+ json_array_foreach(fields, index, field) {
+ const char *fieldName = json_string_value(json_object_get(field, "name"));
+ if (fieldName != NULL) {
+ fputc(' ', stream);
+ fwrite(fieldName, 1, strlen(fieldName), stream);
+ } else {
+ status = PARSE_ERROR;
+ printf("Expected name for field\n");
+ break;
+ }
+ }
+ }
+ } else {
+ status = PARSE_ERROR;
+ printf("Expected array type");
+ }
+ fputc('}', stream);
+ } else {
+ status = PARSE_ERROR;
+ printf("cannot find type with name %s\n", typeName);
+ }
+ } else {
+ status = PARSE_ERROR;
+ printf("Expected array type\n");
+ }
+
+ return status;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/descriptor_translator.h
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/descriptor_translator.h b/remote_services/dynamic_function_interface/descriptor_translator.h
new file mode 100644
index 0000000..b75c8d7
--- /dev/null
+++ b/remote_services/dynamic_function_interface/descriptor_translator.h
@@ -0,0 +1,28 @@
+/**
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#ifndef __DESCRIPTOR_TRANSLATOR_H_
+#define __DESCRIPTOR_TRANSLATOR_H_
+
+#include <sys/queue.h>
+
+typedef struct _interface_descriptor_type interface_descriptor_type;
+
+struct _interface_descriptor_type {
+ TAILQ_HEAD(, _method_descriptor_type) methodDescriptors;
+};
+
+typedef struct _method_descriptor_type method_descriptor_type;
+
+struct _method_descriptor_type {
+ int identifier;
+ char *strIdentifier;
+ char *descriptor;
+ char *name;
+ TAILQ_ENTRY(_method_descriptor_type) entries;
+};
+
+int descriptorTranslator_create(const char *schemaStr, interface_descriptor_type **out);
+int descriptorTranslator_destroy(interface_descriptor_type *desc);
+
+#endif
http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/dfi_log_util.h
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/dfi_log_util.h b/remote_services/dynamic_function_interface/dfi_log_util.h
new file mode 100644
index 0000000..85208ff
--- /dev/null
+++ b/remote_services/dynamic_function_interface/dfi_log_util.h
@@ -0,0 +1,50 @@
+/**
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#ifndef _DFI_LOG_UTIL_H_
+#define _DFI_LOG_UTIL_H_
+
+#define DFI_TEST(cmp) printf("%s", cmp);
+
+typedef void (*logf_ft)(void *handle, int level, const char *file, int line, const char *format, ...);
+
+#define DFI_SETUP_LOG_HEADER(cmp) \
+ void cmp ## _logSetup(logf_ft logf, void *handle, int currentLogLevel);
+
+#define DFI_SETUP_LOG(cmp) \
+ static logf_ft g_logf = NULL; \
+ static void *g_logHandle = NULL; \
+ static int g_currentLogLevel = 1; \
+ \
+ void cmp ## _logSetup(logf_ft logf, void *handle, int currentLogLevel) { \
+ g_currentLogLevel = currentLogLevel; \
+ g_logHandle = handle; \
+ g_logf = logf; \
+ }
+
+#define LOG_LVL_ERROR 1
+#define LOG_LVL_WARNING 2
+#define LOG_LVL_INFO 3
+#define LOG_LVL_DEBUG 4
+
+#define LOG_ERROR(msg, ...) \
+ if (g_logf != NULL && g_currentLogLevel <= LOG_LVL_ERROR) { \
+ g_logf(g_logHandle, LOG_LVL_ERROR, __FILE__, __LINE__, (msg), ##__VA_ARGS__); \
+ }
+
+#define LOG_WARNING(msg, ...) \
+ if (g_logf != NULL && g_currentLogLevel <= LOG_LVL_WARNING) { \
+ g_logf(g_logHandle, LOG_LVL_WARNING, __FILE__, __LINE__, (msg), ##__VA_ARGS__); \
+ }
+
+#define LOG_INFO(msg, ...) \
+ if (g_logf != NULL && g_currentLogLevel <= LOG_LVL_INFO) { \
+ g_logf(g_logHandle, LOG_LVL_INFO, __FILE__, __LINE__, (msg), ##__VA_ARGS__); \
+ }
+
+#define LOG_DEBUG(msg, ...) \
+ if (g_logf != NULL && g_currentLogLevel <= LOG_LVL_DEBUG) { \
+ g_logf(g_logHandle, LOG_LVL_DEBUG, __FILE__, __LINE__, (msg), ##__VA_ARGS__); \
+ }
+
+#endif
http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/dyn_function.c
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/dyn_function.c b/remote_services/dynamic_function_interface/dyn_function.c
new file mode 100644
index 0000000..116803f
--- /dev/null
+++ b/remote_services/dynamic_function_interface/dyn_function.c
@@ -0,0 +1,185 @@
+/*
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#include "dyn_function.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <strings.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <ffi.h>
+
+#include "dyn_type.h"
+#include "dfi_log_util.h"
+
+DFI_SETUP_LOG(dynFunction)
+
+struct _dyn_function_type {
+ dyn_type *arguments;
+ dyn_type *funcReturn;
+ void (*fn)(void);
+ ffi_cif cif;
+};
+
+struct _dyn_closure_type {
+ dyn_type *arguments;
+ dyn_type *funcReturn;
+ ffi_cif cif;
+ ffi_closure *ffiClosure;
+ void (*fn)(void);
+ void (*bind)(void *userData, void *args[], void *ret);
+ void *userData;
+};
+
+
+static int dynFunction_initCif(ffi_cif *cif, dyn_type *arguments, dyn_type *funcReturn);
+static int dynFunction_parseDescriptor(const char *functionDescriptor, dyn_type **arguments, dyn_type **funcReturn);
+static void dynClosure_ffiBind(ffi_cif *cif, void *ret, void *args[], void *userData);
+
+int dynFunction_create(const char *descriptor, void (*fn)(void), dyn_function_type **out) {
+ int status = 0;
+ dyn_function_type *dynFunc = NULL;
+ LOG_DEBUG("Creating dyn function for descriptor '%s'\n", descriptor);
+
+ dynFunc = calloc(1, sizeof(*dynFunc));
+
+ if (dynFunc != NULL) {
+ dynFunc->fn = fn;
+ status = dynFunction_parseDescriptor(descriptor, &dynFunc->arguments, &dynFunc->funcReturn);
+ if (status == 0) {
+ status = dynFunction_initCif(&dynFunc->cif, dynFunc->arguments, dynFunc->funcReturn);
+ }
+ } else {
+ status = 2;
+ }
+
+ if (status == 0) {
+ *out = dynFunc;
+ } else {
+ if (status == 1) {
+ LOG_ERROR("Cannot parse func descriptor '%s'\n", descriptor);
+ } else {
+ LOG_ERROR("Cannot allocate memory for dyn function\n");
+ }
+ }
+ return status;
+}
+
+static int dynFunction_parseDescriptor(const char *descriptor, dyn_type **arguments, dyn_type **funcReturn) {
+ int status = 0;
+ char *startPos = index(descriptor, '(');
+ char *endPos = index(descriptor, ')');
+
+ if (startPos != NULL && endPos != NULL) {
+ int len = endPos - startPos - 1;
+
+ //TODO add names (arg001, arg002, etc)
+ char argDesc[len+3];
+ argDesc[0] = '{';
+ argDesc[len+1] = '}';
+ memcpy(argDesc+1, startPos +1, len);
+ argDesc[len+2] = '\0';
+ LOG_DEBUG("argDesc is '%s'\n", argDesc);
+
+ len = strlen(endPos);
+ char returnDesc[len+1];
+ memcpy(returnDesc, endPos + 1, len);
+ returnDesc[len] = '\0';
+ LOG_DEBUG("returnDesc is '%s'\n", returnDesc);
+
+ status = dynType_create(argDesc, arguments);
+ if (status == 0) {
+ status = dynType_create(returnDesc, funcReturn);
+ }
+ } else {
+ status = 1;
+ }
+
+ return status;
+}
+
+static int dynFunction_initCif(ffi_cif *cif, dyn_type *arguments, dyn_type *returnValue) {
+ int result = 0;
+
+ int count = 0;
+ int i;
+ for (i = 0; arguments->ffiType->elements[i] != NULL; i += 1) {
+ count += 1;
+ }
+
+ ffi_type **args = arguments->ffiType->elements;
+ ffi_type *returnType = returnValue->ffiType;
+
+ int ffiResult = ffi_prep_cif(cif, FFI_DEFAULT_ABI, count, returnType, args);
+ if (ffiResult != FFI_OK) {
+ result = 1;
+ }
+
+ return result;
+}
+
+int dynFunction_destroy(dyn_function_type *dynFunc) {
+ int result = 0;
+ LOG_WARNING("TODO destroy dyn dync\n");
+ return result;
+}
+
+int dynFunction_call(dyn_function_type *dynFunc, void *returnValue, void **argValues) {
+ ffi_call(&dynFunc->cif, dynFunc->fn, returnValue, argValues);
+ return 0;
+}
+
+static void dynClosure_ffiBind(ffi_cif *cif, void *ret, void *args[], void *userData) {
+ dyn_closure_type *dynClosure = userData;
+ dynClosure->bind(dynClosure->userData, args, ret);
+}
+
+int dynClosure_create(const char *descriptor, void (*bind)(void *, void **, void*), void *userData, dyn_closure_type **out) {
+ int status = 0;
+ dyn_closure_type *dynClosure = calloc(1, sizeof(*dynClosure));
+ if (dynClosure != NULL) {
+ dynClosure->bind = bind;
+ dynClosure->userData = userData;
+ status = dynFunction_parseDescriptor(descriptor, &dynClosure->arguments, &dynClosure->funcReturn);
+ if (status == 0) {
+ status = dynFunction_initCif(&dynClosure->cif, dynClosure->arguments, dynClosure->funcReturn);
+ if (status == 0) {
+ dynClosure->ffiClosure = ffi_closure_alloc(sizeof(ffi_closure), (void **)&dynClosure->fn);
+ if (dynClosure->ffiClosure != NULL) {
+ int rc = ffi_prep_closure_loc(dynClosure->ffiClosure, &dynClosure->cif, dynClosure_ffiBind, dynClosure, dynClosure->fn);
+ if (rc != FFI_OK) {
+ status = 1;
+ }
+ } else {
+ status = 2;
+ }
+ }
+ }
+ } else {
+ status = 2;
+ }
+
+ if (status == 0) {
+ *out = dynClosure;
+ }
+ return status;
+}
+
+int dynClosure_getFnPointer(dyn_closure_type *dynClosure, void (**fn)(void)) {
+ int status = 0;
+ if (dynClosure != NULL) {
+ (*fn) = dynClosure->fn;
+ } else {
+ status = 1;
+ }
+ return status;
+}
+
+
+int dynClosure_destroy(dyn_closure_type *dynClosure) {
+ int result = 0;
+ LOG_WARNING("TODO destroy closure\n");
+ return result;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/bdeba2bc/remote_services/dynamic_function_interface/dyn_function.h
----------------------------------------------------------------------
diff --git a/remote_services/dynamic_function_interface/dyn_function.h b/remote_services/dynamic_function_interface/dyn_function.h
new file mode 100644
index 0000000..976f2d7
--- /dev/null
+++ b/remote_services/dynamic_function_interface/dyn_function.h
@@ -0,0 +1,30 @@
+/*
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#ifndef __DYN_FUNCTION_H_
+#define __DYN_FUNCTION_H_
+
+#include <ffi.h>
+#include "dyn_type.h"
+#include "dfi_log_util.h"
+
+/**
+ * Uses the following schema
+ * (Name)([Type]*)Type
+ * e.g add(DD)D or sum({[D[D setA setB})D
+ */
+
+typedef struct _dyn_function_type dyn_function_type;
+typedef struct _dyn_closure_type dyn_closure_type;
+
+DFI_SETUP_LOG_HEADER(dynFunction);
+
+int dynFunction_create(const char *descriptor, void (*fn)(void), dyn_function_type **dynFunc);
+int dynFunction_destroy(dyn_function_type *dynFunc);
+int dynFunction_call(dyn_function_type *dynFunc, void *returnValue, void **argValues);
+
+int dynClosure_create(const char *descriptor, void (*bind)(void *, void **, void*), void *userData, dyn_closure_type **out);
+int dynClosure_getFnPointer(dyn_closure_type *dynClosure, void(**fn)(void));
+int dynClosure_destroy(dyn_closure_type *dynClosure);
+
+#endif