You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by rl...@apache.org on 2019/08/29 12:16:18 UTC

[celix] branch develop updated: Added avpr parsing and serialization (#43)

This is an automated email from the ASF dual-hosted git repository.

rlenferink pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/celix.git


The following commit(s) were added to refs/heads/develop by this push:
     new 48a8fb5  Added avpr parsing and serialization (#43)
48a8fb5 is described below

commit 48a8fb5be15eef23db3cc989bd6e1ace1970de04
Author: idzardh <id...@live.nl>
AuthorDate: Thu Aug 29 14:16:14 2019 +0200

    Added avpr parsing and serialization (#43)
    
    * Added avpr parsing and serialization
    * Update cpp test code
    * Update json serializer to also handle avpr. Leave descriptor parsing intact.
    * Adding all annotations to dyn_type
    * Added test case for custom annotation
---
 bundles/pubsub/mock/CMakeLists.txt                 |    6 +-
 .../src/pubsub_serializer_impl.c                   |  307 ++++--
 bundles/pubsub/test/CMakeLists.txt                 |    1 +
 .../examples/calculator_api/CMakeLists.txt         |    2 +-
 .../org.apache.celix.calc.api.Calculator.avpr      |   44 +
 .../examples/calculator_shell/CMakeLists.txt       |    4 +-
 .../remote_service_admin_dfi/src/dfi_utils.c       |   23 +
 .../remote_service_admin_dfi/src/dfi_utils.h       |    1 +
 .../src/export_registration_dfi.c                  |   11 +-
 .../src/import_registration_dfi.c                  |    9 +-
 .../topology_manager/CMakeLists.txt                |    8 +-
 .../topology_manager/tms_tst/bundle/CMakeLists.txt |    2 +-
 .../bundle/org.apache.celix.test.MyBundle.avpr     |   24 +
 .../org.apache.celix.test.MyBundle.descriptor      |    9 -
 .../topology_manager/tms_tst/tms_tests.cpp         |    6 +-
 libs/CMakeLists.txt                                |    2 +-
 libs/dfi/CMakeLists.txt                            |   33 +-
 libs/dfi/include/dyn_function.h                    |    5 +
 libs/dfi/include/dyn_function_common.h             |   55 +
 libs/dfi/include/dyn_interface.h                   |    4 +
 .../dfi/include/dyn_interface_common.h             |   23 +-
 libs/dfi/include/dyn_message.h                     |    4 +-
 libs/dfi/include/dyn_type.h                        |   19 +
 libs/dfi/include/dyn_type_common.h                 |   64 ++
 libs/dfi/src/dyn_avpr_function.c                   |  352 +++++++
 libs/dfi/src/dyn_avpr_interface.c                  |  290 ++++++
 libs/dfi/src/dyn_avpr_type.c                       |  987 ++++++++++++++++++
 libs/dfi/src/dyn_function.c                        |   29 +-
 libs/dfi/src/dyn_interface.c                       |   16 +-
 libs/dfi/src/dyn_type.c                            |  141 +--
 libs/dfi/src/dyn_type_common.c                     |   81 ++
 libs/dfi/src/json_serializer.c                     |   59 +-
 libs/dfi/test/avro_descriptor_translator_tests.cpp |    1 +
 libs/dfi/test/dyn_avpr_function_tests.cpp          |  620 ++++++++++++
 libs/dfi/test/dyn_avpr_interface_tests.cpp         |  174 ++++
 libs/dfi/test/dyn_avpr_tests.cpp                   |  514 ++++++++++
 libs/dfi/test/dyn_function_tests.cpp               |    3 +-
 libs/dfi/test/dyn_interface_tests.cpp              |    1 +
 libs/dfi/test/dyn_message_tests.cpp                |    1 +
 libs/dfi/test/dyn_type_tests.cpp                   |   11 +
 libs/dfi/test/json_rpc_avpr_tests.cpp              |  384 +++++++
 libs/dfi/test/json_rpc_tests.cpp                   |  147 ++-
 libs/dfi/test/json_serializer_tests.cpp            | 1067 +++++++++++++++++---
 libs/framework/CMakeLists.txt                      |   78 +-
 libs/framework/tst/CMakeLists.txt                  |    2 +
 45 files changed, 5111 insertions(+), 513 deletions(-)

diff --git a/bundles/pubsub/mock/CMakeLists.txt b/bundles/pubsub/mock/CMakeLists.txt
index 2a406d0..98be018 100644
--- a/bundles/pubsub/mock/CMakeLists.txt
+++ b/bundles/pubsub/mock/CMakeLists.txt
@@ -23,11 +23,9 @@ if (CPPUTEST_FOUND)
     add_library(pubsub_mock STATIC
             src/publisher_mock.cc
     )
-    target_include_directories(pubsub_mock PUBLIC api)
     target_link_libraries(pubsub_mock PRIVATE Celix::pubsub_spi ${CPPUTEST_LIBRARY})
-    target_include_directories(pubsub_mock SYSTEM PRIVATE 
-        ${CPPUTEST_INCLUDE_DIR}
-    )
+    target_include_directories(pubsub_mock PUBLIC api)
+    target_include_directories(pubsub_mock SYSTEM PRIVATE ${CPPUTEST_INCLUDE_DIR})
 
     if (ENABLE_TESTING)
         add_executable(pubsubmock_test
diff --git a/bundles/pubsub/pubsub_serializer_json/src/pubsub_serializer_impl.c b/bundles/pubsub/pubsub_serializer_json/src/pubsub_serializer_impl.c
index 4dc9916..5637937 100644
--- a/bundles/pubsub/pubsub_serializer_json/src/pubsub_serializer_impl.c
+++ b/bundles/pubsub/pubsub_serializer_json/src/pubsub_serializer_impl.c
@@ -37,6 +37,14 @@
 #define SYSTEM_BUNDLE_ARCHIVE_PATH  "CELIX_FRAMEWORK_EXTENDER_PATH"
 #define MAX_PATH_LEN    1024
 
+typedef enum
+{
+    FIT_INVALID = 0,
+    FIT_DESCRIPTOR = 1,
+    FIT_AVPR = 2
+}
+FILE_INPUT_TYPE;
+
 struct pubsub_json_serializer {
     bundle_context_pt bundle_context;
     log_helper_pt loghelper;
@@ -47,10 +55,12 @@ struct pubsub_json_serializer {
 static celix_status_t pubsubMsgSerializer_serialize(void* handle, const void* msg, void** out, size_t *outLen);
 static celix_status_t pubsubMsgSerializer_deserialize(void* handle, const void* input, size_t inputLen, void **out);
 static void pubsubMsgSerializer_freeMsg(void* handle, void *msg);
-
+static FILE* openFileStream(FILE_INPUT_TYPE file_input_type, const char* filename, const char* root, /*output*/ char* avpr_fqn, /*output*/ char* path);
+static FILE_INPUT_TYPE getFileInputType(const char* filename);
+static bool readPropertiesFile(const char* properties_file_name, const char* root, /*output*/ char* avpr_fqn, /*output*/ char* path);
 
 typedef struct pubsub_json_msg_serializer_impl {
-    dyn_message_type *msgType;
+    dyn_type *type;
 
     unsigned int msgId;
     const char* msgName;
@@ -61,6 +71,8 @@ static char* pubsubSerializer_getMsgDescriptionDir(bundle_pt bundle);
 static void pubsubSerializer_addMsgSerializerFromBundle(const char *root, bundle_pt bundle, hash_map_pt msgTypesMap);
 static void pubsubSerializer_fillMsgSerializerMap(hash_map_pt msgTypesMap,bundle_pt bundle);
 
+static int pubsubMsgSerializer_convert_descriptor(FILE* file_ptr, pubsub_msg_serializer_t* serializer);
+static int pubsubMsgSerializer_convert_avpr(FILE* file_ptr, pubsub_msg_serializer_t* serializer, const char* fqn);
 
 static void dfi_log(void *handle, int level, const char *file, int line, const char *msg, ...) {
     va_list ap;
@@ -139,8 +151,7 @@ celix_status_t pubsubSerializer_destroySerializerMap(void* handle __attribute__(
     while (hashMapIterator_hasNext(&iter)) {
         pubsub_msg_serializer_t* msgSerializer = hashMapIterator_nextValue(&iter);
         pubsub_json_msg_serializer_impl_t *impl = msgSerializer->handle;
-        dyn_message_type *dynMsg = impl->msgType;
-        dynMessage_destroy(dynMsg); //note msgSer->name and msgSer->version owned by dynType
+        dynType_destroy(impl->type);
         free(msgSerializer); //also contains the service struct.
         free(impl);
     }
@@ -157,9 +168,7 @@ celix_status_t pubsubMsgSerializer_serialize(void *handle, const void* msg, void
     pubsub_json_msg_serializer_impl_t *impl = handle;
 
     char *jsonOutput = NULL;
-    dyn_type* dynType = NULL;
-    dyn_message_type *dynMsg = impl->msgType;
-    dynMessage_getMessageType(dynMsg, &dynType);
+    dyn_type* dynType = impl->type;
 
     if (jsonSerializer_serialize(dynType, msg, &jsonOutput) != 0) {
         status = CELIX_BUNDLE_EXCEPTION;
@@ -177,9 +186,7 @@ celix_status_t pubsubMsgSerializer_deserialize(void* handle, const void* input,
     celix_status_t status = CELIX_SUCCESS;
     pubsub_json_msg_serializer_impl_t *impl = handle;
     void *msg = NULL;
-    dyn_type* dynType = NULL;
-    dyn_message_type *dynMsg = impl->msgType;
-    dynMessage_getMessageType(dynMsg, &dynType);
+    dyn_type* dynType = impl->type;
 
     if (jsonSerializer_deserialize(dynType, (const char*)input, &msg) != 0) {
         status = CELIX_BUNDLE_EXCEPTION;
@@ -193,9 +200,7 @@ celix_status_t pubsubMsgSerializer_deserialize(void* handle, const void* input,
 
 void pubsubMsgSerializer_freeMsg(void* handle, void *msg) {
     pubsub_json_msg_serializer_impl_t *impl = handle;
-    dyn_type* dynType = NULL;
-    dyn_message_type *dynMsg = impl->msgType;
-    dynMessage_getMessageType(dynMsg, &dynType);
+    dyn_type* dynType = impl->type;
     if (dynType != NULL) {
         dynType_free(dynType, msg);
     }
@@ -249,88 +254,222 @@ static char* pubsubSerializer_getMsgDescriptionDir(bundle_pt bundle)
 
 static void pubsubSerializer_addMsgSerializerFromBundle(const char *root, bundle_pt bundle, hash_map_pt msgSerializers)
 {
+    char fqn[MAX_PATH_LEN];
     char path[MAX_PATH_LEN];
-    struct dirent *entry = NULL;
-    DIR *dir = opendir(root);
+    const char* entry_name = NULL;
+    FILE_INPUT_TYPE fileInputType;
+    FILE* stream = NULL;
 
+    const struct dirent *entry = NULL;
+    DIR* dir = opendir(root);
     if (dir) {
         entry = readdir(dir);
     }
 
-    while (entry != NULL) {
-
-        if (strstr(entry->d_name, ".descriptor") != NULL) {
-
-            printf("DMU: Parsing entry '%s'\n", entry->d_name);
-
-            snprintf(path, MAX_PATH_LEN, "%s/%s", root, entry->d_name);
-            FILE *stream = fopen(path,"r");
-
-            if (stream != NULL) {
-                dyn_message_type* msgType = NULL;
-
-                int rc = dynMessage_parse(stream, &msgType);
-                if (rc == 0 && msgType != NULL) {
-
-                    char* msgName = NULL;
-                    rc += dynMessage_getName(msgType,&msgName);
-
-                    version_pt msgVersion = NULL;
-                    rc += dynMessage_getVersion(msgType, &msgVersion);
-
-                    if (rc == 0 && msgName != NULL && msgVersion != NULL) {
-
-                        unsigned int msgId = utils_stringHash(msgName);
-
-                        pubsub_msg_serializer_t *msgSerializer = calloc(1,sizeof(*msgSerializer));
-                        pubsub_json_msg_serializer_impl_t *impl = calloc(1, sizeof(*impl));
-
-                        impl->msgType = msgType;
-                        impl->msgId = msgId;
-                        impl->msgName = msgName;
-                        impl->msgVersion = msgVersion;
-
-                        msgSerializer->handle = impl;
-                        msgSerializer->msgId = impl->msgId;
-                        msgSerializer->msgName = impl->msgName;
-                        msgSerializer->msgVersion = impl->msgVersion;
-                        msgSerializer->serialize = (void*) pubsubMsgSerializer_serialize;
-                        msgSerializer->deserialize = (void*) pubsubMsgSerializer_deserialize;
-                        msgSerializer->freeMsg = (void*) pubsubMsgSerializer_freeMsg;
-
-                        bool clash = hashMap_containsKey(msgSerializers, (void*)(uintptr_t)msgId);
-                        if (clash) {
-                            printf("Cannot add msg %s. clash in msg id %d!!\n", msgName, msgId);
-                            free(msgSerializer);
-                            free(impl);
-                            dynMessage_destroy(msgType);
-                        } else if (msgId != 0) {
-                            printf("Adding %u : %s\n", msgId, msgName);
-                            hashMap_put(msgSerializers, (void*)(uintptr_t)msgId, msgSerializer);
-                        } else {
-                            printf("Error creating msg serializer\n");
-                            free(impl);
-                            free(msgSerializer);
-                            dynMessage_destroy(msgType);
-                        }
-
-                    } else {
-                        printf("Cannot retrieve name and/or version from msg\n");
-                    }
-
-                } else {
-                    printf("DMU: cannot parse message from descriptor %s\n.",path);
-                }
-                fclose(stream);
-            } else {
-                printf("DMU: cannot open descriptor file %s\n.",path);
-            }
+    for (; entry != NULL; entry = readdir(dir)) {
+        entry_name = entry->d_name;
+        printf("DMU: Parsing entry '%s'\n", entry_name);
+        fileInputType = getFileInputType(entry_name);
+        stream = openFileStream(fileInputType, entry_name, root, /*out*/fqn, /*out*/path);
+        if (!stream) {
+            printf("DMU: Cannot open descriptor file: '%s'.\n", path);
+            continue; // Go to next entry in directory
+        }
 
+        pubsub_json_msg_serializer_impl_t *impl = calloc(1, sizeof(*impl));
+        pubsub_msg_serializer_t *msgSerializer = calloc(1,sizeof(*msgSerializer));
+        msgSerializer->handle = impl;
+
+        int translation_result = -1;
+        if (fileInputType == FIT_DESCRIPTOR) {
+            translation_result = pubsubMsgSerializer_convert_descriptor(stream, msgSerializer);
+        }
+        else if (fileInputType == FIT_AVPR) {
+            translation_result = pubsubMsgSerializer_convert_avpr(stream, msgSerializer, fqn);
+        }
+        fclose(stream);
+
+        if (translation_result != 0) {
+            printf("DMU: could not create serializer for '%s'\n", entry_name);
+            free(impl);
+            free(msgSerializer);
+            continue;
+        }
+
+        // serializer has been constructed, try to put in the map
+        if (hashMap_containsKey(msgSerializers, (void *) (uintptr_t) msgSerializer->msgId)) {
+            printf("Cannot add msg %s. clash in msg id %d!!\n", msgSerializer->msgName, msgSerializer->msgId);
+            dynType_destroy(impl->type);
+            free(msgSerializer);
+            free(impl);
+        } else if (msgSerializer->msgId == 0) {
+            printf("Cannot add msg %s. clash in msg id %d!!\n", msgSerializer->msgName, msgSerializer->msgId);
+            dynType_destroy(impl->type);
+            free(msgSerializer);
+            free(impl);
+        }
+        else {
+            hashMap_put(msgSerializers, (void *) (uintptr_t) msgSerializer->msgId, msgSerializer);
         }
-        entry = readdir(dir);
     }
 
     if (dir) {
         closedir(dir);
     }
 }
+static FILE* openFileStream(FILE_INPUT_TYPE file_input_type, const char* filename, const char* root, char* avpr_fqn, char* path) {
+    FILE* result = NULL;
+    memset(path, 0, MAX_PATH_LEN);
+    switch (file_input_type) {
+        case FIT_INVALID:
+            snprintf(path, MAX_PATH_LEN, "Because %s is not a valid file", filename);
+            break;
+
+        case FIT_DESCRIPTOR:
+            snprintf(path, MAX_PATH_LEN, "%s/%s", root, filename);
+            result = fopen(path, "r");
+            break;
+
+        case FIT_AVPR:
+            if (readPropertiesFile(filename, root, avpr_fqn, path)) {
+                result = fopen(path, "r");
+            }
+            break;
+
+        default:
+            printf("DMU: Unknown file input type, returning NULL!\n");
+            break;
+    }
+
+    return result;
+}
+
+static FILE_INPUT_TYPE getFileInputType(const char* filename) {
+    if (strstr(filename, ".descriptor")) {
+        return FIT_DESCRIPTOR;
+    }
+    else if (strstr(filename, ".properties")) {
+        return FIT_AVPR;
+    }
+    else {
+        return FIT_INVALID;
+    }
+}
+
+static bool readPropertiesFile(const char* properties_file_name, const char* root, char* avpr_fqn, char* path) {
+    snprintf(path, MAX_PATH_LEN, "%s/%s", root, properties_file_name); // use path to create path to properties file
+    FILE *properties = fopen(path, "r");
+    if (!properties) {
+        printf("DMU: Could not find or open %s as a properties file in %s\n", properties_file_name, root);
+        return false;
+    }
+
+    *avpr_fqn = '\0';
+    *path = '\0'; //re-use path to create path to avpr file
+    char *p_line = malloc(MAX_PATH_LEN);
+    size_t line_len = MAX_PATH_LEN;
+    while (getline(&p_line, &line_len, properties) >= 0) {
+        if (strncmp(p_line, "fqn=", strlen("fqn=")) == 0) {
+            snprintf(avpr_fqn, MAX_PATH_LEN, "%s", (p_line + strlen("fqn=")));
+            avpr_fqn[strcspn(avpr_fqn, "\n")] = 0;
+        }
+        else if (strncmp(p_line, "avpr=", strlen("avpr=")) == 0) {
+            snprintf(path, MAX_PATH_LEN, "%s/%s", root, (p_line + strlen("avpr=")));
+            path[strcspn(path, "\n")] = 0;
+        }
+    }
+    free(p_line);
+    fclose(properties);
+
+    if (*avpr_fqn == '\0') {
+        printf("CMU: File %s does not contain a fully qualified name for the parser\n", properties_file_name);
+        return false;
+    }
+
+    if (*path == '\0') {
+        printf("CMU: File %s does not contain a location for the avpr file\n", properties_file_name);
+        return false;
+    }
+
+    return true;
+}
+
+static int pubsubMsgSerializer_convert_descriptor(FILE* file_ptr, pubsub_msg_serializer_t* serializer) {
+    dyn_message_type* msgType = NULL;
+    int rc = dynMessage_parse(file_ptr, &msgType);
+    if (rc != 0 || msgType == NULL) {
+        printf("DMU: cannot parse message from descriptor.\n");
+        return -1;
+    }
+
+    char* msgName = NULL;
+    rc += dynMessage_getName(msgType, &msgName);
+
+    version_pt msgVersion = NULL;
+    rc += dynMessage_getVersion(msgType, &msgVersion);
+
+    if (rc != 0 || msgName == NULL || msgVersion == NULL) {
+        printf("DMU: cannot retrieve name and/or version from msg\n");
+        return -1;
+    }
+
+    dyn_type * type = NULL;
+    dynMessage_getMessageType(msgType, &type);
+
+    unsigned int msgId = utils_stringHash(msgName);
+    pubsub_json_msg_serializer_impl_t * handle = (pubsub_json_msg_serializer_impl_t*)serializer->handle;
+    handle->type = type;
+    handle->msgId = msgId;
+    handle->msgName = msgName;
+    handle->msgVersion = msgVersion;
+
+    serializer->msgId = handle->msgId;
+    serializer->msgName = handle->msgName;
+    serializer->msgVersion = handle->msgVersion;
+
+    serializer->serialize = (void*) pubsubMsgSerializer_serialize;
+    serializer->deserialize = (void*) pubsubMsgSerializer_deserialize;
+    serializer->freeMsg = (void*) pubsubMsgSerializer_freeMsg;
+
+    return 0;
+}
+
+static int pubsubMsgSerializer_convert_avpr(FILE* file_ptr, pubsub_msg_serializer_t* serializer, const char* fqn) {
+    if (!file_ptr || !fqn || !serializer) return -2;
+    dyn_type* type = dynType_parseAvpr(file_ptr, fqn);
+
+    if (!type) {
+        printf("DMU: cannot parse avpr file for '%s'\n", fqn);
+        return -1;
+    }
+
+    const char* msgName = dynType_getName(type);
+
+    version_pt msgVersion = NULL;
+    celix_status_t s = version_createVersionFromString(dynType_getMetaInfo(type, "version"), &msgVersion);
+
+    if (s != CELIX_SUCCESS || !msgName) {
+        printf("DMU: cannot retrieve name and/or version from msg\n");
+        if (s == CELIX_SUCCESS) {
+            version_destroy(msgVersion);
+        }
+        return -1;
+    }
+
+    unsigned int msgId = utils_stringHash(msgName);
+    pubsub_json_msg_serializer_impl_t * handle = (pubsub_json_msg_serializer_impl_t*) serializer->handle;
+    handle->type = type;
+    handle->msgId = msgId;
+    handle->msgName = msgName;
+    handle->msgVersion = msgVersion;
+
+    serializer->msgId = handle->msgId;
+    serializer->msgName = handle->msgName;
+    serializer->msgVersion = handle->msgVersion;
+
+    serializer->serialize = (void*) pubsubMsgSerializer_serialize;
+    serializer->deserialize = (void*) pubsubMsgSerializer_deserialize;
+    serializer->freeMsg = (void*) pubsubMsgSerializer_freeMsg;
+
+    return 0;
+}
diff --git a/bundles/pubsub/test/CMakeLists.txt b/bundles/pubsub/test/CMakeLists.txt
index 957745b..f2f9374 100644
--- a/bundles/pubsub/test/CMakeLists.txt
+++ b/bundles/pubsub/test/CMakeLists.txt
@@ -207,6 +207,7 @@ if (BUILD_PUBSUB_PSA_ZMQ)
                 pubsub_sut
                 pubsub_tst
     )
+
     target_link_libraries(pubsub_zmq_tests PRIVATE Celix::pubsub_api ${CPPUTEST_LIBRARIES} ${JANSSON_LIBRARIES} Celix::dfi)
     target_include_directories(pubsub_zmq_tests PRIVATE ${CPPUTEST_INCLUDE_DIR})
     add_test(NAME pubsub_zmq_tests COMMAND pubsub_zmq_tests WORKING_DIRECTORY $<TARGET_PROPERTY:pubsub_zmq_tests,CONTAINER_LOC>)
diff --git a/bundles/remote_services/examples/calculator_api/CMakeLists.txt b/bundles/remote_services/examples/calculator_api/CMakeLists.txt
index 2fb445b..a87945f 100644
--- a/bundles/remote_services/examples/calculator_api/CMakeLists.txt
+++ b/bundles/remote_services/examples/calculator_api/CMakeLists.txt
@@ -19,4 +19,4 @@ add_library(calculator_api INTERFACE)
 target_include_directories(calculator_api INTERFACE include)
 set_target_properties(calculator_api PROPERTIES
     "INTERFACE_CALCULATOR_DESCRIPTOR"
-    "${CMAKE_CURRENT_LIST_DIR}/include/org.apache.celix.calc.api.Calculator.descriptor")
+    "${CMAKE_CURRENT_LIST_DIR}/include/org.apache.celix.calc.api.Calculator.avpr")
diff --git a/bundles/remote_services/examples/calculator_api/include/org.apache.celix.calc.api.Calculator.avpr b/bundles/remote_services/examples/calculator_api/include/org.apache.celix.calc.api.Calculator.avpr
new file mode 100644
index 0000000..b20554e
--- /dev/null
+++ b/bundles/remote_services/examples/calculator_api/include/org.apache.celix.calc.api.Calculator.avpr
@@ -0,0 +1,44 @@
+{
+    "protocol" : "Calculator",
+    "namespace" : "org.apache.celix.calc.api",
+    "version" : "1.3.0",
+    "types" : [ {
+        "type" : "fixed",
+        "name" : "Double",
+        "alias": "double",
+        "size" : 8
+    } ] ,
+    "messages" : {
+        "add" : {
+                "index" : 0,
+                "request" : [ {
+                                "name" : "arg1",
+                                "type" : "Double"
+                            } , {
+                                "name" : "arg2",
+                                "type" : "Double"
+                            } ],
+                "response" : "Double"
+            },
+        "sub" : {
+                "index" : 1,
+                "request" : [ {
+                                "name" : "arg1",
+                                "type" : "Double"
+                            } , {
+                                "name" : "arg2",
+                                "type" : "Double"
+                            } ],
+                "response" : "Double"
+            },
+        "sqrt" : {
+                "index" : 2,
+                "request" : [ {
+                                "name" : "arg",
+                                "type" : "Double"
+                            } ],
+                "response" : "Double"
+            }
+        }
+}
+
diff --git a/bundles/remote_services/examples/calculator_shell/CMakeLists.txt b/bundles/remote_services/examples/calculator_shell/CMakeLists.txt
index 5f3e9e2..14087e3 100644
--- a/bundles/remote_services/examples/calculator_shell/CMakeLists.txt
+++ b/bundles/remote_services/examples/calculator_shell/CMakeLists.txt
@@ -28,7 +28,7 @@ target_include_directories(calculator_shell PRIVATE src)
 target_link_libraries(calculator_shell PRIVATE Celix::shell_api calculator_api)
 
 celix_bundle_files(calculator_shell
-    ../calculator_api/include/org.apache.celix.calc.api.Calculator.descriptor
-    #src/org.apache.celix.calc.api.Calculator.descriptor ##Use this descriptor in case you want to try out versioning!
+    ../calculator_api/include/org.apache.celix.calc.api.Calculator.avpr
+    #src/org.apache.celix.calc.api.Calculator2.descriptor ##Use this descriptor in case you want to try out versioning!
     DESTINATION .
 )
diff --git a/bundles/remote_services/remote_service_admin_dfi/src/dfi_utils.c b/bundles/remote_services/remote_service_admin_dfi/src/dfi_utils.c
index 631152d..74eb259 100644
--- a/bundles/remote_services/remote_service_admin_dfi/src/dfi_utils.c
+++ b/bundles/remote_services/remote_service_admin_dfi/src/dfi_utils.c
@@ -106,3 +106,26 @@ celix_status_t dfi_findDescriptor(bundle_context_pt context, bundle_pt bundle, c
 
     return status;
 }
+
+celix_status_t dfi_findAvprDescriptor(bundle_context_pt context, bundle_pt bundle, const char *name, FILE **out) {
+    celix_status_t  status;
+    char fileName[128];
+
+    snprintf(fileName, 128, "%s.avpr", name);
+
+    long id;
+    status = bundle_getBundleId(bundle, &id);
+
+    if (status == CELIX_SUCCESS) {
+        if (id == 0) {
+            //framework bundle
+            status = dfi_findFileForFramework(context, fileName, out);
+        } else {
+            //normal bundle
+            status = dfi_findFileForBundle(bundle, fileName, out);
+        }
+    }
+
+    return status;
+}
+
diff --git a/bundles/remote_services/remote_service_admin_dfi/src/dfi_utils.h b/bundles/remote_services/remote_service_admin_dfi/src/dfi_utils.h
index cec8aa1..b3056c4 100644
--- a/bundles/remote_services/remote_service_admin_dfi/src/dfi_utils.h
+++ b/bundles/remote_services/remote_service_admin_dfi/src/dfi_utils.h
@@ -26,5 +26,6 @@
 
 
 celix_status_t dfi_findDescriptor(bundle_context_pt context, bundle_pt bundle, const char *name, FILE **out);
+celix_status_t dfi_findAvprDescriptor(bundle_context_pt context, bundle_pt bundle, const char *name, FILE **out);
 
 #endif
diff --git a/bundles/remote_services/remote_service_admin_dfi/src/export_registration_dfi.c b/bundles/remote_services/remote_service_admin_dfi/src/export_registration_dfi.c
index 59d6276..e5b4f46 100644
--- a/bundles/remote_services/remote_service_admin_dfi/src/export_registration_dfi.c
+++ b/bundles/remote_services/remote_service_admin_dfi/src/export_registration_dfi.c
@@ -90,7 +90,7 @@ celix_status_t exportRegistration_create(log_helper_pt helper, service_reference
 
     FILE *descriptor = NULL;
     if (status == CELIX_SUCCESS) {
-        status = dfi_findDescriptor(context, bundle, exports, &descriptor);
+        status = dfi_findAvprDescriptor(context, bundle, exports, &descriptor);
     }
 
     if (status != CELIX_SUCCESS || descriptor == NULL) {
@@ -99,11 +99,12 @@ celix_status_t exportRegistration_create(log_helper_pt helper, service_reference
     }
 
     if (status == CELIX_SUCCESS) {
-        int rc = dynInterface_parse(descriptor, &reg->intf);
+        reg->intf = dynInterface_parseAvpr(descriptor);
+
         fclose(descriptor);
-        if (rc != 0) {
+        if (!reg->intf) {
             status = CELIX_BUNDLE_EXCEPTION;
-            logHelper_log(helper, OSGI_LOGSERVICE_WARNING, "RSA: Error parsing service descriptor.");
+            logHelper_log(helper, OSGI_LOGSERVICE_WARNING, "RSA: Error parsing service descriptor for '%s'", exports);
         }
         else {
             /* Add the interface version as a property in the properties_map */
@@ -260,4 +261,4 @@ celix_status_t exportReference_getExportedService(export_reference_pt reference,
     celix_status_t status = CELIX_SUCCESS;
     *ref = reference->reference;
     return status;
-}
\ No newline at end of file
+}
diff --git a/bundles/remote_services/remote_service_admin_dfi/src/import_registration_dfi.c b/bundles/remote_services/remote_service_admin_dfi/src/import_registration_dfi.c
index a40a560..f7f6567 100644
--- a/bundles/remote_services/remote_service_admin_dfi/src/import_registration_dfi.c
+++ b/bundles/remote_services/remote_service_admin_dfi/src/import_registration_dfi.c
@@ -208,18 +208,19 @@ static celix_status_t importRegistration_createProxy(import_registration_pt impo
     dyn_interface_type* intf = NULL;
     FILE *descriptor = NULL;
 
-    status = dfi_findDescriptor(import->context, bundle, import->classObject, &descriptor);
+    status = dfi_findAvprDescriptor(import->context, bundle, import->classObject, &descriptor);
 
     if (status != CELIX_SUCCESS || descriptor == NULL) {
         //TODO use log helper logHelper_log(helper, OSGI_LOGSERVICE_ERROR, "Cannot find/open descriptor for '%s'", import->classObject);
-        fprintf(stderr, "RSA_DFI: Cannot find/open descriptor for '%s'", import->classObject);
+        fprintf(stdout, "RSA_DFI: Cannot find/open descriptor for '%s'", import->classObject);
         return CELIX_BUNDLE_EXCEPTION;
     }
 
     if (status == CELIX_SUCCESS) {
-        int rc = dynInterface_parse(descriptor, &intf);
+        intf = dynInterface_parseAvpr(descriptor);
         fclose(descriptor);
-        if (rc != 0 || intf==NULL) {
+        if (!intf) {
+            fprintf(stderr, "RSA_DFI: Cannot parse descriptor for '%s'", import->classObject);
             return CELIX_BUNDLE_EXCEPTION;
         }
     }
diff --git a/bundles/remote_services/topology_manager/CMakeLists.txt b/bundles/remote_services/topology_manager/CMakeLists.txt
index 8a4661d..8343d9f 100644
--- a/bundles/remote_services/topology_manager/CMakeLists.txt
+++ b/bundles/remote_services/topology_manager/CMakeLists.txt
@@ -35,10 +35,10 @@ if (RSA_TOPOLOGY_MANAGER)
     if (ENABLE_TESTING)
         find_package(CppUTest REQUIRED)
 	    find_package(Jansson REQUIRED)
- 
-	    include_directories("${JANSSON_INCLUDE_DIR}")
-        include_directories(${CPPUTEST_INCLUDE_DIR})
-        include_directories(${CPPUTEST_EXT_INCLUDE_DIR})
+
+        include_directories("${JANSSON_INCLUDE_DIR}")
+        include_directories("${CPPUTEST_INCLUDE_DIR}")
+        include_directories("${CPPUTEST_EXT_INCLUDE_DIR}")
         add_subdirectory(tms_tst)
    endif (ENABLE_TESTING)
 
diff --git a/bundles/remote_services/topology_manager/tms_tst/bundle/CMakeLists.txt b/bundles/remote_services/topology_manager/tms_tst/bundle/CMakeLists.txt
index 15536e0..8df8399 100644
--- a/bundles/remote_services/topology_manager/tms_tst/bundle/CMakeLists.txt
+++ b/bundles/remote_services/topology_manager/tms_tst/bundle/CMakeLists.txt
@@ -28,7 +28,7 @@ add_celix_bundle(topology_manager_test_bundle
         tst_activator.c   
 )
 celix_bundle_files(topology_manager_test_bundle
-    org.apache.celix.test.MyBundle.descriptor
+    org.apache.celix.test.MyBundle.avpr
     DESTINATION .
 )
 
diff --git a/bundles/remote_services/topology_manager/tms_tst/bundle/org.apache.celix.test.MyBundle.avpr b/bundles/remote_services/topology_manager/tms_tst/bundle/org.apache.celix.test.MyBundle.avpr
new file mode 100644
index 0000000..3876f6f
--- /dev/null
+++ b/bundles/remote_services/topology_manager/tms_tst/bundle/org.apache.celix.test.MyBundle.avpr
@@ -0,0 +1,24 @@
+{
+    "protocol" : "MyBundle",
+    "namespace" : "org.apache.celix",
+    "version" : "1.0.0",
+    "types" : [ {
+        "type" : "fixed",
+        "name" : "Double",
+        "alias": "double",
+        "size" : 8
+    } ] ,
+    "messages" : {
+        "add" : {
+                "index" : 0,
+                "request" : [ {
+                                "name" : "arg1",
+                                "type" : "Double"
+                            } , {
+                                "name" : "arg2",
+                                "type" : "Double"
+                            } ],
+                "response" : "Double"
+            }
+        }
+}
diff --git a/bundles/remote_services/topology_manager/tms_tst/bundle/org.apache.celix.test.MyBundle.descriptor b/bundles/remote_services/topology_manager/tms_tst/bundle/org.apache.celix.test.MyBundle.descriptor
deleted file mode 100644
index 8f04454..0000000
--- a/bundles/remote_services/topology_manager/tms_tst/bundle/org.apache.celix.test.MyBundle.descriptor
+++ /dev/null
@@ -1,9 +0,0 @@
-:header
-type=interface
-name=MyBundle
-version=1.0.0
-:annotations
-classname=org.apache.celix.MyBundle
-:types
-:methods
-add(DD)D=add(#am=handle;PDD#am=pre;*D)N
diff --git a/bundles/remote_services/topology_manager/tms_tst/tms_tests.cpp b/bundles/remote_services/topology_manager/tms_tst/tms_tests.cpp
index c0001aa..70bcadb 100644
--- a/bundles/remote_services/topology_manager/tms_tst/tms_tests.cpp
+++ b/bundles/remote_services/topology_manager/tms_tst/tms_tests.cpp
@@ -85,7 +85,6 @@ extern "C" {
     static service_reference_pt eplRef = NULL;
     static endpoint_listener_pt eplService = NULL; // actually this is the topology manager
 
-
     static void setupFm(void) {
         int rc = 0;
         rc = celixLauncher_launch("config.properties", &framework);
@@ -125,9 +124,12 @@ extern "C" {
 
         rc = bundleContext_getService(context, discRef, (void **)&discMock);
         CHECK_EQUAL(CELIX_SUCCESS, rc);
+
+        printf("==> Finished setup.\n");
     }
 
     static void teardownFm(void) {
+        printf("==> Starting teardown.\n");
         int rc = 0;
 
         rc = bundleContext_ungetService(context, scopeServiceRef, NULL);
@@ -262,7 +264,6 @@ extern "C" {
         framework = NULL;
     }
 
-
     /// \TEST_CASE_ID{1}
     /// \TEST_CASE_TITLE{Test register scope service}
     /// \TEST_CASE_REQ{REQ-1}
@@ -661,7 +662,6 @@ extern "C" {
 
         printf("End: %s\n", __func__);
     }
-
 }
 
 TEST_GROUP(topology_manager_scoped_export) {
diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt
index 5df35a2..8f937e9 100644
--- a/libs/CMakeLists.txt
+++ b/libs/CMakeLists.txt
@@ -28,4 +28,4 @@ add_subdirectory(launcher)
 
 #add_subdirectory(event_admin)# event_admin is unstable
 add_subdirectory(dependency_manager)
-add_subdirectory(dependency_manager_cxx)
\ No newline at end of file
+add_subdirectory(dependency_manager_cxx)
diff --git a/libs/dfi/CMakeLists.txt b/libs/dfi/CMakeLists.txt
index 4bf33f0..6b32a54 100644
--- a/libs/dfi/CMakeLists.txt
+++ b/libs/dfi/CMakeLists.txt
@@ -20,9 +20,13 @@ find_package(Jansson REQUIRED)
 
 set(SOURCES
 	src/dyn_common.c
+	src/dyn_type_common.c
 	src/dyn_type.c
+	src/dyn_avpr_type.c
 	src/dyn_function.c
+	src/dyn_avpr_function.c
 	src/dyn_interface.c
+	src/dyn_avpr_interface.c
 	src/dyn_message.c
 	src/json_serializer.c
 	src/json_rpc.c
@@ -31,8 +35,8 @@ set(SOURCES
 add_library(dfi SHARED ${SOURCES})
 set_target_properties(dfi PROPERTIES OUTPUT_NAME "celix_dfi")
 target_include_directories(dfi PUBLIC
-		$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
-		$<INSTALL_INTERFACE:include/celix/dfi>
+	$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
+	$<INSTALL_INTERFACE:include/celix/dfi>
 )
 
 target_include_directories(dfi SYSTEM PRIVATE
@@ -52,21 +56,24 @@ add_library(Celix::dfi ALIAS dfi)
 
 if (ENABLE_TESTING)
     find_package(CppUTest REQUIRED)
-        
-    include_directories(${CPPUTEST_INCLUDE_DIR})
 
 	add_executable(test_dfi
-		test/dyn_type_tests.cpp
-		test/dyn_function_tests.cpp
-		test/dyn_closure_tests.cpp
-		test/dyn_interface_tests.cpp
-		test/dyn_message_tests.cpp
-		test/json_serializer_tests.cpp
-		test/json_rpc_tests.cpp
+        test/dyn_avpr_tests.cpp
+        test/dyn_type_tests.cpp
+        test/dyn_function_tests.cpp
+        test/dyn_closure_tests.cpp
+        test/dyn_avpr_function_tests.cpp
+        test/dyn_interface_tests.cpp
+        test/dyn_avpr_interface_tests.cpp
+        test/dyn_message_tests.cpp
+        test/json_serializer_tests.cpp
+        test/json_rpc_tests.cpp
+        test/json_rpc_avpr_tests.cpp
 		test/run_tests.cpp
 	)
-	target_link_libraries(test_dfi PRIVATE Celix::dfi Celix::utils ffi::lib ${CPPUTEST_LIBRARY})
-	target_include_directories(test_dfi PRIVATE ffi::lib)
+
+    target_link_libraries(test_dfi PRIVATE Celix::dfi Celix::utils ffi::lib ${JANSSON_LIBRARY} ${CPPUTEST_LIBRARIES})
+    target_include_directories(test_dfi PRIVATE ${JANSSON_INCLUDE_DIRS})
 
     file(COPY ${CMAKE_CURRENT_LIST_DIR}/test/schemas DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
     file(COPY ${CMAKE_CURRENT_LIST_DIR}/test/descriptors DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
diff --git a/libs/dfi/include/dyn_function.h b/libs/dfi/include/dyn_function.h
index a73c941..b7f9a7e 100644
--- a/libs/dfi/include/dyn_function.h
+++ b/libs/dfi/include/dyn_function.h
@@ -35,6 +35,7 @@
 typedef struct _dyn_function_type dyn_function_type;
 
 DFI_SETUP_LOG_HEADER(dynFunction);
+DFI_SETUP_LOG_HEADER(dynAvprFunction);
 
 enum dyn_function_argument_meta {
     DYN_FUNCTION_ARGUMENT_META__STD = 0,
@@ -57,4 +58,8 @@ int dynFunction_call(dyn_function_type *dynFunc, void(*fn)(void), void *returnVa
 int dynFunction_createClosure(dyn_function_type *func, void (*bind)(void *, void **, void*), void *userData, void(**fn)(void));
 int dynFunction_getFnPointer(dyn_function_type *func, void (**fn)(void));
 
+// Avpr parsing
+dyn_function_type * dynFunction_parseAvprWithStr(const char * avpr, const char * fqn);
+dyn_function_type * dynFunction_parseAvpr(FILE * avprStream, const char * fqn);
+
 #endif
diff --git a/libs/dfi/include/dyn_function_common.h b/libs/dfi/include/dyn_function_common.h
new file mode 100644
index 0000000..8ec705a
--- /dev/null
+++ b/libs/dfi/include/dyn_function_common.h
@@ -0,0 +1,55 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef _DYN_FUNCTION_COMMON_H_
+#define _DYN_FUNCTION_COMMON_H_
+
+#include "dyn_function.h"
+
+#include <strings.h>
+#include <stdlib.h>
+#include <ffi.h>
+
+#include "dyn_common.h"
+
+struct _dyn_function_type {
+    char *name;
+    struct types_head *refTypes; //NOTE not owned
+    TAILQ_HEAD(,_dyn_function_argument_type) arguments;
+    ffi_type **ffiArguments;
+    dyn_type *funcReturn;
+    ffi_cif cif;
+
+    //closure part
+    ffi_closure *ffiClosure;
+    void (*fn)(void);
+    void *userData;
+    void (*bind)(void *userData, void *args[], void *ret);
+};
+
+typedef struct _dyn_function_argument_type dyn_function_argument_type;
+struct _dyn_function_argument_type {
+    int index;
+    char *name;
+    enum dyn_function_argument_meta argumentMeta;
+    dyn_type *type;
+    TAILQ_ENTRY(_dyn_function_argument_type) entries;
+};
+
+#endif
diff --git a/libs/dfi/include/dyn_interface.h b/libs/dfi/include/dyn_interface.h
index 54bf41c..0aa7e79 100644
--- a/libs/dfi/include/dyn_interface.h
+++ b/libs/dfi/include/dyn_interface.h
@@ -27,6 +27,7 @@
 #include "version.h"
 
 DFI_SETUP_LOG_HEADER(dynInterface);
+DFI_SETUP_LOG_HEADER(dynAvprInterface);
 
 /* Description string
  *
@@ -62,5 +63,8 @@ int dynInterface_getAnnotationEntry(dyn_interface_type *intf, const char *name,
 int dynInterface_methods(dyn_interface_type *intf, struct methods_head **list);
 int dynInterface_nrOfMethods(dyn_interface_type *intf);
 
+// Avpr parsing
+dyn_interface_type * dynInterface_parseAvprWithStr(const char * avpr);
+dyn_interface_type * dynInterface_parseAvpr(FILE * avprStream);
 
 #endif
diff --git a/bundles/remote_services/remote_service_admin_dfi/src/dfi_utils.h b/libs/dfi/include/dyn_interface_common.h
similarity index 68%
copy from bundles/remote_services/remote_service_admin_dfi/src/dfi_utils.h
copy to libs/dfi/include/dyn_interface_common.h
index cec8aa1..20b9b6d 100644
--- a/bundles/remote_services/remote_service_admin_dfi/src/dfi_utils.h
+++ b/libs/dfi/include/dyn_interface_common.h
@@ -16,15 +16,24 @@
  *specific language governing permissions and limitations
  *under the License.
  */
-#ifndef DFI_UTILS_H_
-#define DFI_UTILS_H_
 
-#include "bundle.h"
-#include "bundle_context.h"
-#include <stdio.h>
-#include "celix_errno.h"
+#ifndef _DYN_INTERFACE_COMMON_H_
+#define _DYN_INTERFACE_COMMON_H_
 
+#include "dyn_interface.h"
 
-celix_status_t dfi_findDescriptor(bundle_context_pt context, bundle_pt bundle, const char *name, FILE **out);
+#include <strings.h>
+#include <stdlib.h>
+#include <ffi.h>
+
+#include "dyn_common.h"
+
+struct _dyn_interface_type {
+    struct namvals_head header;
+    struct namvals_head annotations;
+    struct types_head types;
+    struct methods_head methods;
+    version_pt version;
+};
 
 #endif
diff --git a/libs/dfi/include/dyn_message.h b/libs/dfi/include/dyn_message.h
index d1c8dd7..8a75a73 100644
--- a/libs/dfi/include/dyn_message.h
+++ b/libs/dfi/include/dyn_message.h
@@ -51,6 +51,8 @@ int dynMessage_getHeaderEntry(dyn_message_type *msg, const char *name, char **va
 int dynMessage_getAnnotationEntry(dyn_message_type *msg, const char *name, char **value);
 int dynMessage_getMessageType(dyn_message_type *msg, dyn_type **type);
 
-
+// avpr parsing
+dyn_message_type * dynMessage_parseAvpr(FILE *avprDescriptorStream, const char *fqn);
+dyn_message_type * dynMessage_parseAvprWithStr(const char *avprDescriptor, const char *fqn);
 
 #endif
diff --git a/libs/dfi/include/dyn_type.h b/libs/dfi/include/dyn_type.h
index 554966a..e17db20 100644
--- a/libs/dfi/include/dyn_type.h
+++ b/libs/dfi/include/dyn_type.h
@@ -58,6 +58,10 @@
  * P untyped pointer (void *)
  * t char* string
  * N native int
+ * E enum (int) + meta infos #EnumName=#EnumValue (e.g. #e1=v1;#e2=v2;E)
+ *
+ * < Array //TODO
+ * <(size)[Type] //TODO 
  *
  * ComplexTypes (Struct)
  * {[Type]+ [(Name)(SPACE)]+}
@@ -71,6 +75,7 @@
  * TypeDef 
  * T(Name)=Type;
  *
+ * #OMG style sequence. Struct with uint32_t cap, uint32_t len and a <itemtype> buf[] fields.
  * SequenceType
  * [(Type)
  *
@@ -112,8 +117,16 @@ struct complex_type_entry {
     TAILQ_ENTRY(complex_type_entry) entries;
 };
 
+TAILQ_HEAD(meta_properties_head, meta_entry);
+struct meta_entry {
+    char *name;
+    char *value;
+    TAILQ_ENTRY(meta_entry) entries;
+};
+
 //logging
 DFI_SETUP_LOG_HEADER(dynType);
+DFI_SETUP_LOG_HEADER(dynAvprType);
 
 //generic
 int dynType_parse(FILE *descriptorStream, const char *name, struct types_head *refTypes, dyn_type **type);
@@ -128,6 +141,8 @@ size_t dynType_size(dyn_type *type);
 int dynType_type(dyn_type *type);
 int dynType_descriptorType(dyn_type *type);
 const char * dynType_getMetaInfo(dyn_type *type, const char *name);
+int dynType_metaEntries(dyn_type *type, struct meta_properties_head **entries);
+const char * dynType_getName(dyn_type *type);
 
 //complexType
 int dynType_complex_indexForName(dyn_type *type, const char *name);
@@ -152,4 +167,8 @@ int dynType_text_allocAndInit(dyn_type *type, void *textLoc, const char *value);
 //simple
 void dynType_simple_setValue(dyn_type *type, void *inst, void *in);
 
+// avpr parsing
+dyn_type * dynType_parseAvpr(FILE *avprStream, const char *fqn);
+dyn_type * dynType_parseAvprWithStr(const char *avpr, const char *fqn);
+
 #endif
diff --git a/libs/dfi/include/dyn_type_common.h b/libs/dfi/include/dyn_type_common.h
new file mode 100644
index 0000000..e19a172
--- /dev/null
+++ b/libs/dfi/include/dyn_type_common.h
@@ -0,0 +1,64 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef _DYN_TYPE_COMMON_H_
+#define _DYN_TYPE_COMMON_H_
+
+#include "dyn_common.h"
+#include "dyn_type.h"
+
+#include <ffi.h>
+
+#include "dfi_log_util.h"
+
+DFI_SETUP_LOG_HEADER(dynTypeCommon);
+
+struct _dyn_type {
+    char *name;
+    char descriptor;
+    int type;
+    ffi_type *ffiType;
+    dyn_type *parent;
+    struct types_head *referenceTypes; //NOTE: not owned
+    struct types_head nestedTypesHead;
+    struct meta_properties_head metaProperties;
+    union {
+        struct {
+            struct complex_type_entries_head entriesHead;
+            ffi_type structType; //dyn_type.ffiType points to this
+            dyn_type **types; //based on entriesHead for fast access
+        } complex;
+        struct {
+            ffi_type seqType; //dyn_type.ffiType points to this
+            dyn_type *itemType;
+        } sequence;
+        struct {
+            dyn_type *typedType;
+        } typedPointer;
+        struct {
+            dyn_type *ref;
+        } ref;
+    };
+};
+
+dyn_type * dynType_findType(dyn_type *type, char *name);
+ffi_type * dynType_ffiType(dyn_type * type);
+void dynType_prepCif(ffi_type *type);
+
+#endif
diff --git a/libs/dfi/src/dyn_avpr_function.c b/libs/dfi/src/dyn_avpr_function.c
new file mode 100644
index 0000000..5ce62cb
--- /dev/null
+++ b/libs/dfi/src/dyn_avpr_function.c
@@ -0,0 +1,352 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include "dyn_function.h"
+#include "dyn_function_common.h"
+
+#include "jansson.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "dyn_common.h"
+#include "dyn_type.h"
+
+DFI_SETUP_LOG(dynAvprFunction)
+
+#define FQN_SIZE 256
+#define ARG_SIZE 32
+
+// Section: static function declarations
+dyn_function_type * dynAvprFunction_parseFromJson(json_t * const root, const char * fqn);
+static json_t const * const dynAvprFunction_findFunc(const char * fqn, json_t * const messagesObject, const char * parentNamespace);
+static bool dynAvprFunction_parseFunc(dyn_function_type * func, json_t const * const jsonFuncObject, json_t * const root, const char * fqn, const char * parentNamespace);
+inline static bool dynAvprFunction_parseArgument(dyn_function_type * func, size_t index, json_t const * entry, json_t * const root, const char * namespace, char * argBuffer, char * typeBuffer);
+inline static bool dynAvprFunction_parseReturn(dyn_function_type * func, size_t index, json_t const * const response_type, json_t * const root, const char * namespace, char * typeBuffer);
+inline static bool dynAvprFunction_createHandle(dyn_function_type * func);
+inline static dyn_function_argument_type * dynAvprFunction_prepareArgumentEntry(const char * name);
+inline static dyn_type * dynAvprFunction_createVoidType();
+inline static dyn_type * dynAvprFunction_createNativeType();
+inline static bool dynAvprFunction_initCif(dyn_function_type * func, size_t nofArguments);
+
+// Section: extern function definitions
+ffi_type * dynType_ffiType(dyn_type *type);
+dyn_type * dynAvprType_parseFromJson(json_t * const root, const char * fqn);
+dyn_type * dynAvprType_createNestedForFunction(dyn_type * store_type, const char* fqn);
+dyn_type * dynAvprType_parseFromTypedJson(json_t * const root, json_t const * const type_entry, const char * namespace);
+void dynAvprType_constructFqn(char* destination, int size, const char * possibleFqn, const char * ns);
+
+// Section: function definitions
+dyn_function_type * dynFunction_parseAvpr(FILE * avprStream, const char * fqn) {
+    json_error_t error;
+    json_t *root = json_loadf(avprStream, JSON_REJECT_DUPLICATES, &error);
+    if (!root) {
+        LOG_ERROR("function_parseAvpr: Error decoding json: line %d: %s", error.line, error.text);
+        return NULL;
+    }
+
+    dyn_function_type * func = dynAvprFunction_parseFromJson(root, fqn);
+    json_decref(root);
+    return func;
+}
+
+dyn_function_type * dynFunction_parseAvprWithStr(const char * avpr, const char * fqn) {
+    FILE *avprStream = fmemopen((char*)avpr, strlen(avpr), "r");
+
+    if (!avprStream) {
+        LOG_ERROR("function_parseAvprWithStr: Error creating mem stream for descriptor string. %s", strerror(errno)); 
+        return NULL;
+    }
+
+    dyn_function_type *returnValue = dynFunction_parseAvpr(avprStream, fqn);
+    fclose(avprStream);
+    return returnValue;
+}
+
+dyn_function_type * dynAvprFunction_parseFromJson(json_t * const root, const char * fqn) {
+    bool valid = true;
+    dyn_function_type *func = calloc(1, sizeof(*func));
+
+    if (!json_is_object(root)) {
+        LOG_ERROR("ParseFunction: Error decoding json, root should be an object");
+        valid = false;
+    }
+
+    // Get base namespace
+    const char *parentNamespace = json_string_value(json_object_get(root, "namespace"));
+    if (valid && !parentNamespace) {
+        LOG_ERROR("ParseFunction: No namespace found in root, or it is null!");
+        valid = false;
+    }
+
+    // Get messages array
+    json_t * const messagesObject = json_object_get(root, "messages");
+    if (valid && !json_is_object(messagesObject)) {
+        LOG_ERROR("ParseFunction: No messages, or it is not an object");
+        valid = false;
+    }
+
+    if (valid && !dynAvprFunction_parseFunc(func, dynAvprFunction_findFunc(fqn, messagesObject, parentNamespace), root, fqn, parentNamespace)) {
+        LOG_ERROR("parseAvpr: Destroying incorrect result");
+        dynFunction_destroy(func);
+        func = NULL;
+    }
+    else {
+        LOG_DEBUG("ParseFunction: Succesfully parsed \"%s\"", fqn)
+    }
+
+    return func;
+}
+
+static json_t const * const dynAvprFunction_findFunc(const char * fqn, json_t * const messagesObject, const char * parentNamespace) {
+    char nameBuffer[FQN_SIZE];
+    const char * func_name;
+    json_t const * func_entry;
+    json_t const * local_ns;
+    json_object_foreach(messagesObject, func_name, func_entry) {
+        local_ns = json_object_get(func_entry, "namespace");
+        dynAvprType_constructFqn(nameBuffer, FQN_SIZE, func_name, json_is_string(local_ns) ? json_string_value(local_ns) : parentNamespace);
+
+        LOG_DEBUG("FindFunc: Comparing: %s and %s", fqn, nameBuffer);
+        if (strcmp(nameBuffer, fqn) == 0) {
+            LOG_DEBUG("FindFunc: Found function definition for %s", fqn);
+            return func_entry;
+        }
+    }
+    LOG_INFO("FindFunc: Did not find function definition for %s", fqn);
+    return NULL;
+}
+
+static bool dynAvprFunction_parseFunc(dyn_function_type * func, json_t const * const jsonFuncObject, json_t * const root, const char * fqn, const char * parentNamespace) {
+    if (!jsonFuncObject) {
+        LOG_WARNING("ParseFunc: Received NULL, function not found, nothing to parse");
+        return false;
+    }
+
+    func->name = strdup(fqn);
+    if (!func->name) {
+        LOG_ERROR("ParseFunc: Error allocating memory for function name %s", fqn);
+        return false;
+    }
+
+    json_t const * const argument_list = json_object_get(jsonFuncObject, "request");
+    if (!json_is_array(argument_list)) {
+        LOG_ERROR("ParseFunc: Request is not an array");
+        free(func->name);
+        return false;
+    }
+
+    json_t const * const json_function_namespace = json_object_get(jsonFuncObject, "namespace");
+    const char* function_namespace = json_is_string(json_function_namespace) ? json_string_value(json_function_namespace) : parentNamespace;
+
+    // Parse requests argument array
+    TAILQ_INIT(&func->arguments);
+    if (!dynAvprFunction_createHandle(func)) {
+        LOG_ERROR("ParseFunc: Could not creat handle for %s", fqn);
+        free(func->name);
+        return false;
+    }
+    char argBuffer[ARG_SIZE]; 
+    char typeBuffer[FQN_SIZE];
+    size_t index;
+    json_t const * arg_entry;
+    json_array_foreach(argument_list, index, arg_entry) {
+        if (!dynAvprFunction_parseArgument(func, index+1, arg_entry, root, function_namespace, argBuffer, typeBuffer)) { /* Offset index to account for the handle */
+            LOG_ERROR("ParseFunc: Could not parse argument %d for %s", index, fqn);
+            return false;
+        }
+        LOG_DEBUG("Added argument %d", index+1);
+    }
+    index++;
+
+    json_t const * const response_type = json_object_get(jsonFuncObject, "response");
+    if (!dynAvprFunction_parseReturn(func, index, response_type, root, function_namespace, typeBuffer)) {
+        LOG_ERROR("ParseFunc: Could not parse return type for %s", fqn);
+        free(func->name);
+        return false;
+    }
+    index+=1;
+
+    func->funcReturn = dynAvprFunction_createNativeType();
+    if (!func->funcReturn) {
+        LOG_ERROR("ParseFunc: Could not create error indicator for %s", fqn);
+        return false;
+    }
+
+    if (!dynAvprFunction_initCif(func, index)) {
+        LOG_ERROR("ParseFunc: Could not prepare cif information");
+        return false;
+    }
+
+    // Everything successfull
+    return true;
+}
+
+inline static bool dynAvprFunction_parseArgument(dyn_function_type * func, size_t index, json_t const * entry, json_t * const root, const char * namespace, char * argBuffer, char * typeBuffer) {
+    const char * entry_name = json_string_value(json_object_get(entry, "name"));
+    if (!entry_name)  {
+        LOG_INFO("ParseArgument: Could not find argument name for %d, using default", index);
+        snprintf(argBuffer, ARG_SIZE, "arg%04lu", index);
+        entry_name = argBuffer;
+    }
+
+    dyn_type * entry_dyn_type = dynAvprType_parseFromTypedJson(root, json_object_get(entry, "type"), namespace);
+    if (!entry_dyn_type) {
+        LOG_ERROR("ParseArgument: Could not parse type for argument");
+        return false;
+    }
+
+    if (json_is_true(json_object_get(entry, "ptr"))) {
+        entry_dyn_type = dynAvprType_createNestedForFunction(entry_dyn_type, entry_name);
+        if (!entry_dyn_type) {
+            LOG_ERROR("ParseArgument: Could not create pointer argument for %s", entry_name);
+            dynType_destroy(entry_dyn_type);
+            return false;
+        }
+    }
+
+    dyn_function_argument_type *arg = dynAvprFunction_prepareArgumentEntry(entry_name);
+    if (!arg) {
+        dynType_destroy(entry_dyn_type);
+        return false;
+    }
+
+    arg->index = index;
+    arg->type = entry_dyn_type;
+    arg->argumentMeta = DYN_FUNCTION_ARGUMENT_META__STD;
+
+    TAILQ_INSERT_TAIL(&func->arguments, arg, entries);
+    return true;
+}
+
+inline static bool dynAvprFunction_parseReturn(dyn_function_type * func, size_t index, json_t const * const response_type, json_t * const root, const char * namespace, char * typeBuffer) {
+    dyn_type * return_dyn_type = dynAvprType_parseFromTypedJson(root, response_type, namespace);
+    if (!return_dyn_type) {
+        LOG_ERROR("ParseReturn: Could not parse return argument");
+        return false;
+    }
+
+    dyn_type * out_dyn_type = dynAvprType_createNestedForFunction(return_dyn_type, "out");
+    if (!out_dyn_type) {
+        LOG_ERROR("ParseReturn: Could not create pointer for return type");
+        dynType_destroy(return_dyn_type);
+        return false;
+    }
+
+    dyn_function_argument_type *arg = dynAvprFunction_prepareArgumentEntry("out");
+    if (!arg) {
+        LOG_ERROR("ParseReturn: Could not create nested type for return type");
+        dynType_destroy(out_dyn_type);
+        return false;
+    }
+
+    arg->index = index;
+
+    // Check descriptor type, if it is a struct ({), sequence ([) or a string (t) an extra level of indirection is needed
+    int descriptor = dynType_descriptorType(return_dyn_type);
+    if (descriptor == '{' || descriptor == '[') {
+        out_dyn_type = dynAvprType_createNestedForFunction(out_dyn_type, "out");
+        if (!out_dyn_type) {
+            LOG_ERROR("ParseReturn: Could not create nested type for return complex type");
+            dynType_destroy(out_dyn_type);
+            return false;
+        }
+        arg->argumentMeta = DYN_FUNCTION_ARGUMENT_META__OUTPUT;
+    }
+    else {
+        arg->argumentMeta = DYN_FUNCTION_ARGUMENT_META__PRE_ALLOCATED_OUTPUT;
+    }
+
+    arg->type = out_dyn_type;
+    TAILQ_INSERT_TAIL(&func->arguments, arg, entries);
+    return true;
+}
+
+inline static bool dynAvprFunction_createHandle(dyn_function_type * func) {
+    dyn_function_argument_type * arg = dynAvprFunction_prepareArgumentEntry("handle");
+    if (!arg) {
+        return false;
+    }
+
+    arg->index = 0;
+    arg->type = dynAvprFunction_createVoidType();
+    if (!arg->type) {
+        free(arg);
+        return false;
+    }
+
+    arg->argumentMeta = DYN_FUNCTION_ARGUMENT_META__HANDLE;
+    TAILQ_INSERT_TAIL(&func->arguments, arg, entries);
+    return true;
+}
+
+inline static dyn_function_argument_type * dynAvprFunction_prepareArgumentEntry(const char * name) {
+    if (!name) {
+        LOG_ERROR("PrepareArgumentEntry: Need name to create argument entry");
+        return NULL;
+    }
+
+    dyn_function_argument_type *arg = calloc(1, sizeof(*arg));
+    arg->name = strndup(name, ARG_SIZE);
+    return arg;
+}
+
+inline static dyn_type * dynAvprFunction_createVoidType() {
+    const char * entry = "{ \
+                \"protocol\" : \"types\", \
+                \"namespace\" : \"dummy\", \
+                \"types\" : [ { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"VoidPtr\", \
+                    \"alias\" : \"void_ptr\", \
+                    \"size\" : 4 \
+                  } ] ,\
+                \"messages\" : { }\
+                }";
+    return dynType_parseAvprWithStr(entry, "dummy.VoidPtr");
+}
+
+inline static dyn_type * dynAvprFunction_createNativeType() {
+    const char * entry = "{ \
+                \"protocol\" : \"types\", \
+                \"namespace\" : \"dummy\", \
+                \"types\" : [ { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"NativeInt\", \
+                    \"alias\" : \"native_int\", \
+                    \"size\" : 4 \
+                  } ] ,\
+                \"messages\" : { }\
+                }";
+    return dynType_parseAvprWithStr(entry, "dummy.NativeInt");
+}
+
+inline static bool dynAvprFunction_initCif(dyn_function_type * func, size_t nofArguments) {
+    func->ffiArguments = calloc(nofArguments, sizeof(ffi_type*));
+    dyn_function_argument_type *entry = NULL;
+    TAILQ_FOREACH(entry, &func->arguments, entries) {
+        func->ffiArguments[entry->index] = dynType_ffiType(entry->type);
+    }
+
+    ffi_type *returnType = dynType_ffiType(func->funcReturn);
+    int ffi_result = ffi_prep_cif(&func->cif, FFI_DEFAULT_ABI, nofArguments, returnType, func->ffiArguments);
+
+    return ffi_result == FFI_OK;
+}
+
diff --git a/libs/dfi/src/dyn_avpr_interface.c b/libs/dfi/src/dyn_avpr_interface.c
new file mode 100644
index 0000000..1424d30
--- /dev/null
+++ b/libs/dfi/src/dyn_avpr_interface.c
@@ -0,0 +1,290 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include "dyn_interface.h"
+#include "dyn_interface_common.h"
+
+#include "jansson.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "dyn_common.h"
+#include "dyn_type.h"
+#include "dyn_function.h"
+
+DFI_SETUP_LOG(dynAvprInterface)
+
+#define STR_LENGTH 1024
+#define FQN_SIZE 256
+#define ARG_SIZE 32
+
+// Section: function definitions
+inline static dyn_interface_type * dynAvprInterface_initializeInterface();
+inline static bool dynAvprInterface_createHeader(dyn_interface_type* intf, json_t * const root);
+inline static bool dynAvprInterface_createAnnotations(dyn_interface_type* intf, json_t * const root);
+inline static bool dynAvprInterface_createTypes(dyn_interface_type* intf, json_t * const root, const char* parent_ns);
+inline static bool dynAvprInterface_createMethods(dyn_interface_type* intf, json_t * const root, const char* parent_ns);
+static bool dynAvprInterface_insertNamValEntry(struct namvals_head *head, const char* name, const char* value);
+static struct namval_entry * dynAvprInterface_createNamValEntry(const char* name, const char* value);
+
+// Section: extern function definitions
+ffi_type * dynType_ffiType(dyn_type *type);
+dyn_type * dynAvprType_parseFromJson(json_t * const root, const char * fqn);
+dyn_function_type * dynAvprFunction_parseFromJson(json_t * const root, const char * fqn);
+int dynInterface_checkInterface(dyn_interface_type *intf);
+void dynAvprType_constructFqn(char * destination, int size, const char * possibleFqn, const char * ns);
+
+// Function definitions
+dyn_interface_type * dynInterface_parseAvprWithStr(const char * avpr) {
+    FILE *avprStream = fmemopen((char*)avpr, strlen(avpr), "r");
+
+    if (!avprStream) {
+        LOG_ERROR("interface_parseAvprWithStr: Error creating mem stream for descriptor string. %s", strerror(errno)); 
+        return NULL;
+    }
+
+    dyn_interface_type *returnValue = dynInterface_parseAvpr(avprStream);
+    fclose(avprStream);
+    return returnValue;
+}
+
+dyn_interface_type * dynInterface_parseAvpr(FILE * avprStream) {
+    dyn_interface_type *intf = NULL;
+    bool valid = true;
+    json_error_t error;
+    json_t *root = json_loadf(avprStream, JSON_REJECT_DUPLICATES, &error);
+    if (!root) {
+        LOG_ERROR("interface_parseAvpr: Error decoding json: line %d: %s", error.line, error.text);
+        valid = false;
+    }
+
+    if (valid && !json_is_object(root)) {
+        LOG_ERROR("interface_parseAvpr: Error decoding json, root should be an object");
+        valid = false;
+    }
+
+    const char *parent_ns = json_string_value(json_object_get(root, "namespace"));
+    if (valid && !parent_ns) {
+        LOG_ERROR("interface_parseAvpr: No namespace found in root, or it is null!");
+        valid = false;
+    }
+
+    json_t * const messagesObject = json_object_get(root, "messages");
+    if (valid && !json_is_object(messagesObject)) {
+        LOG_ERROR("interface_parseAvpr: No messages, or it is not an object");
+        valid = false;
+    }
+
+    if (valid) {
+        intf = dynAvprInterface_initializeInterface();
+        valid = intf != NULL;
+    }
+
+    valid = valid && dynAvprInterface_createHeader(intf, root);
+    valid = valid && dynAvprInterface_createAnnotations(intf, root);
+    valid = valid && dynAvprInterface_createTypes(intf, root, parent_ns);
+    valid = valid && dynAvprInterface_createMethods(intf, root, parent_ns);
+
+    valid = valid && 0 == dynInterface_checkInterface(intf);
+
+    json_decref(root);
+    if (valid) {
+        LOG_DEBUG("Parsing of avpr interface successful");
+        return intf;
+    }
+    else {
+        LOG_ERROR("Parsing of avpr interface failed");
+        dynInterface_destroy(intf);
+        return NULL;
+    }
+}
+
+inline static dyn_interface_type * dynAvprInterface_initializeInterface() {
+    dyn_interface_type *intf = calloc(1, sizeof(*intf));
+
+    TAILQ_INIT(&intf->header);
+    TAILQ_INIT(&intf->annotations);
+    TAILQ_INIT(&intf->types);
+    TAILQ_INIT(&intf->methods);
+
+    return intf;
+}
+
+inline static bool dynAvprInterface_createHeader(dyn_interface_type* intf, json_t * const root) {
+    // type
+    if (!dynAvprInterface_insertNamValEntry(&intf->header, "type", "interface")) {
+        return false;
+    }
+
+    // name (protocol in avpr-speak)
+    if (!dynAvprInterface_insertNamValEntry(&intf->header, "name", json_string_value(json_object_get(root, "protocol")))) {
+        return false;
+    }
+
+    // version
+    if (!dynAvprInterface_insertNamValEntry(&intf->header, "version", json_string_value(json_object_get(root, "version")))) {
+        return false;
+    }
+
+    // Also parse version in the intf->version for cel
+    char* version = NULL;
+    dynInterface_getVersionString(intf, &version);
+    if (!version) {
+        LOG_ERROR("No version string in header");
+        return false;
+    }
+
+    if (CELIX_SUCCESS != version_createVersionFromString(version, &(intf->version))) {
+        LOG_ERROR("Invalid version (%s) in parsed descriptor\n", version);
+        return false;
+    }
+
+    return true;
+}
+
+inline static bool dynAvprInterface_createAnnotations(dyn_interface_type* intf, json_t * const root) {
+    // namespace
+    if (!dynAvprInterface_insertNamValEntry(&intf->annotations, "namespace", json_string_value(json_object_get(root, "namespace")))) {
+        return false;
+    }
+
+    // TODO: other annotations?
+
+    return true;
+}
+
+inline static bool dynAvprInterface_createTypes(dyn_interface_type* intf, json_t * const root, const char* parent_ns) {
+    json_t const * const types_array = json_object_get(root, "types");
+    if (!types_array || !json_is_array(types_array)) {
+        LOG_ERROR("json: types is not an array or it does not exists!");
+        return false;
+    }
+
+    char name_buffer[FQN_SIZE];
+    json_t const * entry;
+    json_t const * local_ns;
+    char const * name;
+    size_t index;
+    struct type_entry *t_entry = NULL;
+    json_array_foreach(types_array, index, entry) {
+        local_ns = json_object_get(entry, "namespace");
+        name = json_string_value(json_object_get(entry, "name"));
+        if (!name) {
+            LOG_ERROR("Type entry %llu has no name", index);
+            return false;
+        }
+        dynAvprType_constructFqn(name_buffer, FQN_SIZE, name, json_is_string(local_ns) ? json_string_value(local_ns) : parent_ns);
+
+        t_entry = calloc(1, sizeof(*t_entry));
+        t_entry->type = dynAvprType_parseFromJson(root, name_buffer);
+        if (!t_entry->type) {
+            free(t_entry);
+            return false;
+        }
+
+        TAILQ_INSERT_TAIL(&intf->types, t_entry, entries);
+    }
+
+    return true;
+}
+
+inline static bool dynAvprInterface_createMethods(dyn_interface_type* intf, json_t * const root, const char* parent_ns) {
+    json_t * const messages_object = json_object_get(root, "messages");
+    if (!messages_object || !json_is_object(messages_object)) {
+        LOG_ERROR("json: messages is not an object or it does not exist!");
+        return false;
+    }
+
+    char name_buffer[FQN_SIZE];
+    json_t const * func_entry;
+    json_t const * local_ns;
+    json_t const * j_index;
+    char const * func_name;
+    struct method_entry *m_entry = NULL;
+    json_object_foreach(messages_object, func_name, func_entry) {
+        local_ns = json_object_get(func_entry, "namespace");
+        dynAvprType_constructFqn(name_buffer, FQN_SIZE, func_name, json_is_string(local_ns) ? json_string_value(local_ns) : parent_ns);
+
+        m_entry = calloc(1, sizeof(*m_entry));
+        m_entry->dynFunc = dynAvprFunction_parseFromJson(root, name_buffer);
+        if (!m_entry->dynFunc) {
+            free(m_entry);
+            return false;
+        }
+
+        j_index = json_object_get(func_entry, "index");
+        if (!json_is_integer(j_index)) {
+            LOG_ERROR("For parsing an interface annotate all functions with an integer index");
+            dynFunction_destroy(m_entry->dynFunc);
+            free(m_entry);
+            return false;
+        }
+
+        m_entry->index = json_integer_value(j_index);
+        m_entry->id = strndup(func_name, STR_LENGTH);
+        if (!m_entry->id) {
+            LOG_ERROR("Could not allocate memory for method entry name %s", func_name);
+            dynFunction_destroy(m_entry->dynFunc);
+            free(m_entry);
+            return false;
+        }
+
+        m_entry->name = strndup(func_name, STR_LENGTH); // For avpr these are the same
+        if (!m_entry->id) {
+            LOG_ERROR("Could not allocate memory for method entry id %s", func_name);
+            dynFunction_destroy(m_entry->dynFunc);
+            free(m_entry);
+            return false;
+        }
+        TAILQ_INSERT_TAIL(&intf->methods, m_entry, entries);
+    }
+
+    // Parsed all methods
+    return true;
+}
+
+static bool dynAvprInterface_insertNamValEntry(struct namvals_head *head, const char* name, const char* value) {
+    struct namval_entry *entry = dynAvprInterface_createNamValEntry(name, value);
+    if (!entry) {
+        return false;
+    }
+    else {
+        TAILQ_INSERT_TAIL(head, entry, entries);
+        return true;
+    }
+}
+
+static struct namval_entry * dynAvprInterface_createNamValEntry(const char* name, const char* value) {
+    if (!name) {
+        LOG_ERROR("Passed null-ptr to name of name-value entry creation function, unknown what type to create");
+        return NULL;
+    }
+
+    if (!value) {
+        LOG_ERROR("Received a name (%s) but no value, did the look-up for a value fail?", name);
+        return NULL;
+    }
+
+    struct namval_entry *entry = calloc(1, sizeof(*entry));
+    entry->name = strndup(name, STR_LENGTH);
+    entry->value = strndup(value, STR_LENGTH);
+    return entry;
+}
+
diff --git a/libs/dfi/src/dyn_avpr_type.c b/libs/dfi/src/dyn_avpr_type.c
new file mode 100644
index 0000000..fccf610
--- /dev/null
+++ b/libs/dfi/src/dyn_avpr_type.c
@@ -0,0 +1,987 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include "dyn_type.h"
+
+#include "jansson.h"
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <ffi.h>
+
+#include "dyn_type.h"
+#include "dyn_type_common.h"
+#include "version.h"
+
+DFI_SETUP_LOG(dynAvprType)
+
+#define STR_LENGTH 1024
+#define FQN_SIZE 256
+
+enum JsonTypeType {INVALID=0, SIMPLE=1, ARRAY=2, REFERENCE=3, SELF_REFERENCE=4};
+
+dyn_type * dynAvprType_parseFromJson(json_t * const root, const char * fqn);
+dyn_type * dynAvprType_createNestedForFunction(dyn_type * store_type, const char* fqn);
+dyn_type * dynAvprType_parseFromTypedJson(json_t * const root, json_t const * const type_entry, const char * namespace);
+void dynAvprType_constructFqn(char* destination, int size, const char* possibleFqn, const char* ns);
+
+// Any
+static json_t const * dynAvprType_findType(char const * const fqn, json_t const * const array_object, const char * ns);
+static dyn_type * dynAvprType_parseAny(dyn_type * root, dyn_type * parent, json_t const * const jsonObject, json_t const * const array_object, const char * parent_ns);
+static dyn_type * dynAvprType_initializeType(dyn_type * parent);
+
+// Record
+static dyn_type * dynAvprType_parseRecord(dyn_type * root, dyn_type * parent, json_t const * const record_obj, json_t const * const array_object, const char* parent_ns, dyn_type * ref_type);
+static inline dyn_type * dynAvprType_prepareRecord(dyn_type * parent, json_t const ** fields, json_t const * const record_obj);
+static inline bool dynAvprType_finalizeRecord(dyn_type * type, const size_t size);
+static inline struct complex_type_entry* dynAvprType_prepareRecordEntry(dyn_type * parent, json_t const * const entry_object);
+static inline struct complex_type_entry * dynAvprType_parseRecordEntry(dyn_type * root, dyn_type * parent, json_t const * const entry_object, json_t const * const array_object, const char * fqn_parent, const char * parent_ns, const char * record_ns, dyn_type * ref_type);
+static inline enum JsonTypeType dynAvprType_getRecordEntryType(json_t const * const entry_object, const char * fqn_parent, char * name_buffer, const char * namespace);
+
+// Reference
+static dyn_type * dynAvprType_parseReference(dyn_type * root, const char * name_buffer, json_t const * const array_object, const char * parent_ns);
+static dyn_type * dynAvprType_parseSelfReference(dyn_type * root, dyn_type * parent, const char * name_buffer, json_t const * const array_object, const char * parent_ns, dyn_type * ref_type);
+static dyn_type * dynAvprType_initializeReferenceType(dyn_type * type_pointer);
+static inline struct type_entry * dynAvprType_prepareNestedEntry(dyn_type * const parent, const char * fqn, bool allocate);
+
+// Enum
+static dyn_type * dynAvprType_parseEnum(dyn_type * parent, json_t const * const enum_obj, const char * parent_ns);
+static inline struct meta_entry * dynAvprType_createMetaEntry(const char* enum_entry_name);
+static inline bool dynAvprType_metaEntrySetValue(struct meta_entry * meta_entry_ptr, json_t const * const values_array, size_t index);
+static inline void dynAvprType_parseEnumValue(char** enumvalue);
+
+// Array
+static dyn_type * dynAvprType_parseArray(dyn_type * root, dyn_type * parent, json_t const * const array_entry_obj, json_t const * const array_object, char * name_buffer, const char * parent_ns, const char * record_ns);
+
+// Fixed
+static dyn_type * dynAvprType_parseFixed(dyn_type * parent, json_t const * const fixed_object, const char * parent_ns);
+static inline int dynAvprType_fixedTypeToFfi(json_t const * const simple_obj, ffi_type ** output_ffi_type);
+
+// General
+static char * dynAvprType_createFqnFromJson(json_t const * const jsonObject, const char * namespace);
+static inline enum JsonTypeType dynAvprType_getType(json_t const * const json_type);
+static inline void dynAvprType_createVersionMetaEntry(dyn_type * type, json_t const * const root, json_t const * const array_object, const char* parent_ns);
+static inline void dynAvprType_createAnnotationEntries(dyn_type * type, json_t const * const array_object, const char* parent_ns);
+
+// fqn = fully qualified name
+dyn_type * dynType_parseAvpr(FILE* avprStream, const char *fqn) {
+    json_error_t error;
+    json_t *root = json_loadf(avprStream, JSON_REJECT_DUPLICATES, &error);
+    if (!root) {
+        LOG_ERROR("parseAvpr: Error decoding json: line %d: %s", error.line, error.text);
+        return NULL;
+    }
+
+    dyn_type * type = dynAvprType_parseFromJson(root, fqn);
+    json_decref(root);
+    return type;
+}
+
+dyn_type * dynType_parseAvprWithStr(const char* avpr, const char *fqn) {
+    FILE *avprStream = fmemopen((char*)avpr, strlen(avpr), "r");
+
+    if (!avprStream) {
+        LOG_ERROR("parseAvprWithStr: Error creating mem stream for descriptor string. %s", strerror(errno)); 
+        return NULL;
+    }
+
+    dyn_type *returnValue = dynType_parseAvpr(avprStream, fqn);
+    fclose(avprStream);
+    return returnValue;
+}
+
+// Based on the fqn passed in, try to find an entry in the array_object with that name, the current namespace is defined by the parameter ns
+static json_t const * dynAvprType_findType(char const * const fqn, json_t const * const array_object, const char * ns) {
+    char fqn_buffer[FQN_SIZE];
+    size_t index;
+    json_t const * type_entry;
+
+    json_array_foreach(array_object, index, type_entry) {
+        const char* entry_name = json_string_value(json_object_get(type_entry, "name"));
+        if (entry_name) {
+            const char* entry_ns = json_string_value(json_object_get(type_entry, "namespace"));
+            snprintf(fqn_buffer, FQN_SIZE, "%s.%s", entry_ns ? entry_ns : ns, entry_name);
+            if (strcmp(fqn, fqn_buffer) == 0) {
+                return type_entry; // Found
+            }
+        }
+        else {
+            LOG_INFO("FindType: found a type with no name, check your json configuration, skipping this entry for now...");
+        }
+    }
+    return NULL; // Not found
+}
+
+dyn_type * dynAvprType_parseFromJson(json_t * const root, const char * fqn) {
+    // Initialize type
+    bool valid = true;
+    if (!json_is_object(root)) {
+        LOG_ERROR("parseAvpr: Error decoding json, root should be an object");
+        valid = false;
+    }
+
+    // Get base namespace
+    const char *parent_ns = json_string_value(json_object_get(root, "namespace"));
+    if (valid && !parent_ns) {
+        LOG_ERROR("parseAvpr: No namespace found in root, or it is null!");
+        valid = false;
+    }
+
+    // Get types array
+    json_t* typesArrayObject = json_object_get(root, "types");
+    if (valid && !json_is_array(typesArrayObject)) {
+        LOG_ERROR("parseAvpr: types should be an array!");
+        valid = false;
+    }
+
+    // Try to find the fqn and parse if it is found, if any error occurs during parsing, return NULL
+    dyn_type * type = NULL;
+    if (valid) {
+        type = dynAvprType_parseAny(NULL, NULL, dynAvprType_findType(fqn, typesArrayObject, parent_ns), typesArrayObject, parent_ns);
+        valid = type != NULL;
+    }
+
+    // Add version as a meta entry
+    if (valid) {
+    	LOG_DEBUG("parseAvpr: Parsing successful, adding version entry and annotations");
+        dynAvprType_createVersionMetaEntry(type, root, typesArrayObject, parent_ns);
+        // Add any other annotation fields that are not in [type, name, fields, version, alias]
+        dynAvprType_createAnnotationEntries(type, typesArrayObject, parent_ns);
+
+    }
+
+    if (valid) {
+        LOG_DEBUG("Found %s", fqn);
+    }
+    else {
+        LOG_ERROR("Not found %s", fqn);
+    }
+
+    return type;
+}
+
+dyn_type * dynAvprType_createNestedForFunction(dyn_type * store_type, const char* fqn) {
+    if (!store_type) {
+        return NULL;
+    }
+
+    // Created dyn_type for reference argument in function
+    dyn_type * entry_ref_type = dynAvprType_initializeType(NULL);
+    if (!entry_ref_type) {
+        dynType_destroy(store_type);
+        return NULL;
+    }
+
+    // Create pointer type and enter type in nested types
+    struct type_entry *entry = dynAvprType_prepareNestedEntry(entry_ref_type, fqn, false);
+    if (!entry) {
+        free(entry_ref_type);
+        return NULL;
+    }
+
+    entry->type = store_type;
+    entry_ref_type->type = DYN_TYPE_TYPED_POINTER;
+    entry_ref_type->descriptor = '*';
+    entry_ref_type->ffiType = &ffi_type_pointer;
+
+    // Create reference type for the sub type
+    dyn_type * sub_type = dynAvprType_initializeType(entry_ref_type);
+    if (!sub_type) {
+        dynType_destroy(store_type);
+        free(entry_ref_type);
+        free(entry);
+        return NULL;
+    }
+
+    entry_ref_type->typedPointer.typedType = sub_type;
+    sub_type->type = DYN_TYPE_REF;
+    sub_type->descriptor = 'l';
+    sub_type->ref.ref = entry->type;
+
+    return entry_ref_type;
+}
+
+// To be used for dyn_function parsing of return and parameter arrays
+dyn_type * dynAvprType_parseFromTypedJson(json_t * const root, json_t const * const type_entry, const char * namespace) {
+    if (!type_entry) {
+        LOG_ERROR("Need a type entry to parse, but got a NULL pointer");
+        return NULL;
+    }
+
+    dyn_type * ret_type = NULL;
+    enum JsonTypeType elType = dynAvprType_getType(type_entry);
+    char name_buffer[FQN_SIZE];
+    switch (elType) {
+        case SIMPLE:
+            dynAvprType_constructFqn(name_buffer, FQN_SIZE, json_string_value(type_entry), namespace);
+            ret_type = dynAvprType_parseFromJson(root, name_buffer);
+            break;
+
+        case ARRAY:
+            ret_type = dynAvprType_parseArray(ret_type, NULL, type_entry, json_object_get(root, "types"), name_buffer, namespace, namespace);
+            if (!ret_type) {
+                LOG_ERROR("Error allocating memory for type");
+                return NULL;
+            }
+            break;
+
+        case INVALID:
+            /* fall through */
+        case REFERENCE:
+            /* fall through */
+        default:
+            LOG_ERROR("ParseFromTypedJson: Received illegal type : %d", elType);
+            break;
+    }
+
+    return ret_type;
+}
+
+void dynAvprType_constructFqn(char* destination, int size, const char* possibleFqn, const char* ns) {
+    const bool isAlreadyFqn = strchr(possibleFqn, '.') != NULL;
+    snprintf(destination, size, "%s%s%s", isAlreadyFqn ? "" : ns, isAlreadyFqn ? "" : ".", possibleFqn);
+}
+
+static dyn_type * dynAvprType_parseAny(dyn_type * root, dyn_type * parent, json_t const * const jsonObject, json_t const * const array_object, const char * parent_ns) {
+    if (!jsonObject) {
+        LOG_WARNING("Any: Received NULL, type not found, nothing to parse");
+        return NULL;
+    }
+
+    const char* type_name = json_string_value(json_object_get(jsonObject, "type"));
+    if (!type_name) {
+        LOG_ERROR("Any: \"type\" entry is not a string or does not exist");
+        return NULL;
+    }
+
+    dyn_type * type = NULL;
+    LOG_DEBUG("Any: Parsing a %s", type_name);
+    if (strcmp(type_name, "record") == 0) {
+        type = dynAvprType_parseRecord(root, parent, jsonObject, array_object, parent_ns, NULL);
+    }
+    else if (strcmp(type_name, "fixed") == 0) {
+        type = dynAvprType_parseFixed(parent, jsonObject, parent_ns);
+    }
+    else if (strcmp(type_name, "enum") == 0) {
+        type = dynAvprType_parseEnum(parent, jsonObject, parent_ns);
+    }
+    else {
+        LOG_ERROR("Any: Unrecognized type: %s", type_name);
+    }
+
+    return type;
+}
+
+static dyn_type * dynAvprType_initializeType(dyn_type * parent) {
+    dyn_type * type = calloc(1, sizeof(*type));
+    TAILQ_INIT(&type->nestedTypesHead);
+    TAILQ_INIT(&type->metaProperties);
+    type->parent = parent;
+    return type;
+}
+
+static dyn_type * dynAvprType_parseRecord(dyn_type * root, dyn_type * parent, json_t const * const record_obj, json_t const * const array_object, const char * parent_ns, dyn_type * ref_type) {
+    json_t const * fields = NULL;
+    dyn_type * type = dynAvprType_prepareRecord(parent, &fields, record_obj); // also sets fields correctly
+    if (!type) {
+        return NULL;
+    }
+
+    // Check if namespace is present, otherwise set it equal to parent
+    const char* record_ns = json_string_value(json_object_get(record_obj, "namespace"));
+    if (!record_ns) {
+        record_ns = parent_ns;
+    }
+
+    // Create namespace + name for storage in type->name (to preserve namespacing)
+    char fqn_buffer[FQN_SIZE];
+    snprintf(fqn_buffer, FQN_SIZE, "%s.%s", record_ns, json_string_value(json_object_get(record_obj, "name")));
+    type->name = strndup(fqn_buffer, STR_LENGTH);
+    if (!type->name) {
+        LOG_ERROR("Record: failed to allocate memory for type->name");
+        dynType_destroy(type);
+        return NULL;
+    }
+
+    // If root is NULL, this is the root type
+    if (!root) {
+        root = type;
+    }
+
+    // Loop over json_fields and parse each entry
+    size_t counter;
+    json_t *element;
+    json_array_foreach(fields, counter, element) {
+        LOG_DEBUG("Record: parsing field [%s](%s) at %d", json_string_value(json_object_get(element, "type")), json_string_value(json_object_get(element, "name")), counter);
+
+        struct complex_type_entry * entry = dynAvprType_parseRecordEntry(root, type, element, array_object, fqn_buffer, parent_ns, record_ns, ref_type);
+        if (!entry) {
+            LOG_ERROR("Record: Parsing record entry %d failed", counter);
+            dynType_destroy(type);
+            return NULL;
+        }
+
+        TAILQ_INSERT_TAIL(&type->complex.entriesHead, entry, entries);
+    }
+
+    return dynAvprType_finalizeRecord(type, counter) ? type : NULL;
+}
+
+// Initializes the type pointer with the correct information for a record (complex type)
+static inline dyn_type * dynAvprType_prepareRecord(dyn_type * parent, json_t const ** fields, json_t const * const record_obj) {
+    const char * name = json_string_value(json_object_get(record_obj, "name"));
+    if (!name) {
+        LOG_ERROR("Record: \"name\" entry is missing");
+        return NULL;
+    }
+
+    *fields = json_object_get(record_obj, "fields");
+    if (!json_is_array(*fields)) {
+        LOG_WARNING("Record: \"fields\" is not an array or does not exist");
+        return NULL;
+    }
+
+    dyn_type * type = dynAvprType_initializeType(parent);
+    if (!type) {
+        return NULL;
+    }
+
+    type->type = DYN_TYPE_COMPLEX;
+    type->descriptor = '{';
+    type->ffiType = &type->complex.structType;
+    type->complex.structType.type = FFI_TYPE_STRUCT;
+    TAILQ_INIT(&type->complex.entriesHead);
+    return type;
+}
+
+// Create the ffi types for quick access and link the dyn_types
+static inline bool dynAvprType_finalizeRecord(dyn_type * type, const size_t size) {
+    type->complex.structType.elements = calloc(size+1, sizeof(ffi_type*));
+    type->complex.structType.elements[size] = NULL;
+    struct complex_type_entry *entry = NULL;
+    int index = 0;
+    TAILQ_FOREACH(entry, &type->complex.entriesHead, entries) {
+        type->complex.structType.elements[index++] = dynType_ffiType(entry->type);
+    }
+
+    // set types for every element for access
+    index = 0;
+    type->complex.types = calloc(size, sizeof(dyn_type*));
+    TAILQ_FOREACH(entry, &type->complex.entriesHead, entries) {
+        type->complex.types[index++] = entry->type;
+    }
+
+    dynType_prepCif(type->ffiType);
+    return true;
+}
+
+static inline struct complex_type_entry * dynAvprType_parseRecordEntry(dyn_type * root, dyn_type * parent, json_t const * const entry_object, json_t const * const array_object, const char * fqn_parent, const char * parent_ns, const char * record_ns, dyn_type * ref_type) {
+    struct complex_type_entry *entry = dynAvprType_prepareRecordEntry(parent, entry_object);
+    if (!entry) {
+        return NULL;
+    }
+
+    char name_buffer[FQN_SIZE];
+    switch (dynAvprType_getRecordEntryType(entry_object, fqn_parent, name_buffer, record_ns)) {
+        case SIMPLE:
+                LOG_DEBUG("RecordEntry: Looking for type: %s", name_buffer);
+                entry->type = dynAvprType_parseAny(root, parent, dynAvprType_findType(name_buffer, array_object, parent_ns), array_object, parent_ns);
+                break;
+
+        case REFERENCE:
+                LOG_DEBUG("RecordEntry: Found a ptr type, creating a reference %s", name_buffer);
+                entry->type = dynAvprType_parseReference(root, name_buffer, array_object, parent_ns);
+                break;
+
+        case SELF_REFERENCE:
+                LOG_DEBUG("RecordEntry: Creating a self_reference for %s", name_buffer);
+                entry->type = dynAvprType_parseSelfReference(root, parent, name_buffer, array_object, parent_ns, ref_type);
+                break;
+
+        case ARRAY:
+                LOG_DEBUG("RecordEntry: Parsing array: %s", name_buffer);
+                entry->type = dynAvprType_parseArray(root, parent, json_object_get(entry_object, "type"), array_object, name_buffer, parent_ns, record_ns);
+                break;
+
+        case INVALID:
+            /* fall through */
+        default:
+                LOG_ERROR("RecordEntry: Illegal record entry for %s", json_string_value(json_object_get(entry_object, "name")));
+                entry->type = NULL;
+                break;
+    }
+
+    if (entry->type) {
+        return entry;
+    }
+    else {
+        free(entry->name);
+        free(entry);
+        return NULL;
+    }
+}
+
+static inline struct complex_type_entry* dynAvprType_prepareRecordEntry(dyn_type * parent, json_t const * const entry_object) {
+    struct complex_type_entry *entry = NULL;
+
+    const char * entry_name = json_string_value(json_object_get(entry_object, "name"));
+    if (!entry_name) {
+        LOG_ERROR("Could not find name in entry");
+        return NULL;
+    }
+
+    entry = calloc(1, sizeof(*entry));
+    entry->name = strndup(entry_name, STR_LENGTH);
+    return entry;
+}
+
+// Returns correct type and sets the fqn in the buffer if it is a simple type (not for array because arrays can be nested 
+static inline enum JsonTypeType dynAvprType_getRecordEntryType(json_t const * const entry_object, const char * fqn_parent, char * name_buffer, const char * namespace) {
+    json_t const * const json_type = json_object_get(entry_object, "type");
+    if (!json_type) {
+        LOG_WARNING("RecordEntry: No type entry");
+        return INVALID;
+    }
+
+    enum JsonTypeType elType = dynAvprType_getType(json_type);
+    if (elType == SIMPLE) {
+        dynAvprType_constructFqn(name_buffer, FQN_SIZE, json_string_value(json_type), namespace);
+        if (strcmp(name_buffer, fqn_parent) == 0) {
+            elType = SELF_REFERENCE;
+        } else if (json_is_true(json_object_get(entry_object, "ptr"))) {
+            elType = REFERENCE;
+        }
+    }
+
+    return elType;
+}
+
+static dyn_type * dynAvprType_parseReference(dyn_type * root, const char * name_buffer, json_t const * const array_object, const char * parent_ns) {
+    dyn_type * type = dynAvprType_initializeType(NULL);
+    if (!type) {
+        return NULL;
+    }
+
+    dyn_type *subType = dynAvprType_initializeReferenceType(type);
+    if (!subType) {
+        free(type);
+        return NULL;
+    }
+
+    // First try to find if it already exists
+    LOG_DEBUG("Reference: looking for %s", name_buffer);
+    dyn_type *ref = dynType_findType(root, (char*) name_buffer);
+    if (ref) {
+        if (ref->type == DYN_TYPE_INVALID) {
+            LOG_ERROR("Reference: found incomplete type");
+            free(type);
+            return NULL;
+        }
+        else {
+            subType->ref.ref = ref;
+            return type;
+        }
+    }
+
+    // if not found, Generate the reference type in root
+    LOG_DEBUG("Reference: looking for %s in array", name_buffer);
+    json_t const * const refType = dynAvprType_findType(name_buffer, array_object, parent_ns);
+    if (!refType) {
+        LOG_ERROR("ParseReference: Could not find %s", name_buffer);
+        free(subType);
+        free(type);
+        return NULL;
+    }
+
+    bool success = true;
+    struct type_entry *entry = dynAvprType_prepareNestedEntry(root, name_buffer, true);
+    dyn_type * tmp = entry->type;
+    if (!entry) {
+        LOG_ERROR("Reference: could not create nested entry");
+        success = false;
+    }
+
+    if (success) {
+        entry->type = dynAvprType_parseAny(root, NULL, refType, array_object, parent_ns); 
+        if (!entry->type) {
+            free(entry);
+            success = false;
+        }
+    }
+
+    free(tmp->name);
+    free(tmp);
+
+    if (success) {
+        LOG_DEBUG("Added new type to root:");
+        subType->ref.ref = entry->type;
+        return type;
+    }
+    else {
+        dynType_destroy(subType);
+        dynType_destroy(type);
+        return NULL;
+    }
+}
+
+static dyn_type * dynAvprType_parseSelfReference(dyn_type * root, dyn_type * parent, const char * name_buffer, json_t const * const array_object, const char * parent_ns, dyn_type * ref_type) {
+    dyn_type * type = dynAvprType_initializeType(parent);
+    if (!type) {
+        return NULL;
+    }
+
+    dyn_type * sub_type = dynAvprType_initializeReferenceType(type);
+    if (!sub_type) {
+        free(type);
+        return NULL;
+    }
+
+    sub_type->ref.ref = parent;
+    return type;
+}
+
+// Assumes type_pointer is already present and alloc'd!
+static dyn_type * dynAvprType_initializeReferenceType(dyn_type * type_pointer) {
+    type_pointer->type = DYN_TYPE_TYPED_POINTER;
+    type_pointer->descriptor = '*';
+    type_pointer->ffiType = &ffi_type_pointer;
+
+    dyn_type *sub_type = dynAvprType_initializeType(type_pointer);
+    if (!sub_type) {
+        LOG_ERROR("Could not create reference type");
+        return NULL;
+    }
+
+    type_pointer->typedPointer.typedType = sub_type;
+    sub_type->type = DYN_TYPE_REF;
+    sub_type->descriptor = 'l';
+    return sub_type;
+
+}
+
+static inline struct type_entry * dynAvprType_prepareNestedEntry(dyn_type * const parent, const char * fqn, bool allocate) {
+    struct type_entry *entry = calloc(1, sizeof(*entry));
+    if (allocate) {
+        entry->type = calloc(1, sizeof(*entry->type));
+        entry->type->name = strndup(fqn, STR_LENGTH);
+
+        // Initialize information
+        entry->type->parent = parent;
+        entry->type->type = DYN_TYPE_INVALID;
+        TAILQ_INIT(&entry->type->nestedTypesHead);
+        TAILQ_INIT(&entry->type->metaProperties);
+    }
+    
+    TAILQ_INSERT_TAIL(&parent->nestedTypesHead, entry, entries);
+    return entry;
+}
+
+static dyn_type * dynAvprType_parseEnum(dyn_type * parent, json_t const * const enum_obj, const char * parent_ns) {
+    dyn_type * type = dynAvprType_initializeType(parent);
+    if (!type) {
+        return NULL;
+    }
+
+    char * fqn = dynAvprType_createFqnFromJson(enum_obj, parent_ns);
+    if (!fqn) {
+        free(type);
+        return NULL;
+    }
+
+    json_t * symbolArray = json_object_get(enum_obj, "symbols");
+    if (!json_is_array(symbolArray)) {
+        LOG_WARNING("Expected \"symbols\" to be an array for enum %s", fqn);
+        free(fqn);
+        free(type);
+        return NULL;
+    }
+
+    json_t * values_array = json_object_get(enum_obj, "EnumValues");
+    if (json_is_array(values_array) && json_array_size(values_array) != json_array_size(symbolArray)) {
+        LOG_WARNING("Expected \"symbols\" and \"EnumValues\" arrays to be of the same size");
+        free(fqn);
+        free(type);
+        return NULL;
+    }
+
+    const size_t max = json_array_size(symbolArray);
+    bool valid = true;
+    size_t counter = 0;
+    json_t *enumeta_entry_ptr;
+	for (; valid && counter < max && (enumeta_entry_ptr = json_array_get(symbolArray, counter)); counter++) {
+        struct meta_entry * meta_entry_ptr = dynAvprType_createMetaEntry(json_string_value(enumeta_entry_ptr));
+        if (meta_entry_ptr && dynAvprType_metaEntrySetValue(meta_entry_ptr, values_array, counter)) {
+            LOG_DEBUG("Added enum entry with name: %s and value: %s", meta_entry_ptr->name, meta_entry_ptr->value);
+            TAILQ_INSERT_TAIL(&type->metaProperties, meta_entry_ptr, entries);
+        }
+        else {
+            valid = false;
+        }
+    }
+
+    if (valid) {
+        type->name = fqn;
+        type->type = DYN_TYPE_SIMPLE;
+        type->descriptor = 'E';
+        type->ffiType = &ffi_type_sint32;
+        return type;
+    }
+    else {
+        free(fqn);
+        dynType_destroy(type);
+        return NULL;
+    }
+}
+
+static inline struct meta_entry * dynAvprType_createMetaEntry(const char* enum_entry_name) {
+    if (!enum_entry_name) {
+        LOG_ERROR("CreateMetaEntry: passed null pointer, no name present?");
+        return NULL;
+    }
+
+    struct meta_entry *entry = calloc(1, sizeof(*entry));
+    entry->name = strndup(enum_entry_name, STR_LENGTH);
+    return entry;
+}
+
+static inline bool dynAvprType_metaEntrySetValue(struct meta_entry * meta_entry_ptr, json_t const * const values_array, size_t index) {
+    if (!meta_entry_ptr) {
+        return false;
+    }
+
+    if (values_array) {
+        const char* enumValue = json_string_value(json_array_get(values_array, index));
+        if (!enumValue) {
+            LOG_WARNING("MetaEntrySetValue: could not get the enum value from the \"EnumValues\" list at index %lu", index);
+            return false;
+        }
+
+        meta_entry_ptr->value = strndup(enumValue, STR_LENGTH);
+        if (!meta_entry_ptr->value) {
+            LOG_ERROR("MetaEntrySetValue: could not allocate memory for meta_entry->value");
+            return false;
+        }
+        dynAvprType_parseEnumValue(&meta_entry_ptr->value);
+    }
+    else {
+        const int bufsize = sizeof(index) * CHAR_BIT + 1;
+        meta_entry_ptr->value = calloc(bufsize, sizeof(char));
+
+        snprintf(meta_entry_ptr->value, bufsize, "%lu", index);
+    }
+
+    return true;
+}
+
+static inline void dynAvprType_parseEnumValue(char** enumvalue) {
+    char* str = *enumvalue;
+    if (!str) {
+        LOG_ERROR("Do not pass null pointer to this function");
+        return;
+    }
+
+    // Remove whitespace
+    int i, j = 0;
+    for (i = 0; str[i] != '\0'; i++) {
+        if (!isspace((unsigned char) str[i])) {
+            str[j++] = str[i];
+        }
+    }
+    str[j] = '\0';
+
+    //create the substring if an equals sign is found
+    char* equalssign = strrchr(str, '=');
+    if (equalssign) {
+        memmove(str, equalssign+1, strlen(equalssign-1));
+    }
+}
+
+static ffi_type *seq_types[] = {&ffi_type_uint32, &ffi_type_uint32, &ffi_type_pointer, NULL};
+
+static dyn_type * dynAvprType_parseArray(dyn_type * root, dyn_type * parent, json_t const * const array_entry_obj, json_t const * const array_object, char * name_buffer, const char * parent_ns, const char * record_ns) {
+    dyn_type * type = dynAvprType_initializeType(parent);
+    if (!type) {
+        return NULL;
+    }
+
+    type->type = DYN_TYPE_SEQUENCE;
+    type->descriptor = '[';
+
+    type->sequence.seqType.elements = seq_types;
+    type->sequence.seqType.type = FFI_TYPE_STRUCT;
+    type->sequence.seqType.size = 0;
+    type->sequence.seqType.alignment = 0;
+    type->sequence.itemType = NULL;
+
+    json_t const * const itemsEntry = json_object_get(array_entry_obj, "items");
+    if (json_is_object(itemsEntry)) { // is nested?
+        LOG_DEBUG("ParseArray: Found nested array");
+        json_t const * const nested_array_object = json_object_get(array_entry_obj, "items");
+        type->sequence.itemType = dynAvprType_parseArray(root, type, nested_array_object, array_object, name_buffer, parent_ns, record_ns);
+    }
+    else if (json_is_string(itemsEntry)) { // is a named item?
+        LOG_DEBUG("ParseArray: Found type, parsing");
+        dynAvprType_constructFqn(name_buffer, FQN_SIZE, json_string_value(itemsEntry), record_ns);
+        type->sequence.itemType = dynAvprType_parseAny(root, type, dynAvprType_findType(name_buffer, array_object, parent_ns), array_object, parent_ns);
+    }
+    else {
+        LOG_ERROR("ParseArray: Unrecognized array structure: \"items\" is neither a nested array nor a type");
+    }
+
+    if (type->sequence.itemType) {
+        type->ffiType = &type->sequence.seqType;
+        dynType_prepCif(&type->sequence.seqType);
+    }
+    else {
+        free(type);
+        type = NULL;
+    }
+
+    return type;
+}
+
+static dyn_type * dynAvprType_parseFixed(dyn_type * parent, json_t const * const fixed_object, const char * parent_ns) {
+    dyn_type * type = dynAvprType_initializeType(parent);
+    if (!type) {
+        return NULL;
+    }
+
+    ffi_type * ffiType = NULL;
+    int descriptor = dynAvprType_fixedTypeToFfi(fixed_object, &ffiType);
+
+    if (!ffiType || descriptor == '0') {
+        LOG_ERROR("Invalid simple type, received wrong ffi type!");
+        free(type);
+        return NULL;
+    }
+
+    if (!json_is_string(json_object_get(fixed_object, "name"))) {
+        LOG_ERROR("Invalid simple type, need a name");
+        free(type);
+        return NULL;
+    }
+
+    type->name = dynAvprType_createFqnFromJson(fixed_object, parent_ns);
+    if (!type->name) {
+        free(type);
+        return NULL;
+    }
+
+    type->type = (descriptor == 't') ? DYN_TYPE_TEXT : DYN_TYPE_SIMPLE;
+    type->descriptor = descriptor;
+    type->ffiType = ffiType;
+    return type;
+}
+
+static inline int dynAvprType_fixedTypeToFfi(json_t const * const simple_obj, ffi_type ** output_ffi_type) {
+    const int size = json_integer_value(json_object_get(simple_obj, "size"));
+    const bool sign = json_is_true(json_object_get(simple_obj, "signed"));
+    const char * alias = json_string_value(json_object_get(simple_obj, "alias"));
+    const int s_size = sign ? size : -size;
+
+    LOG_DEBUG("Simple fixed type: size = %d, signed = %s, alias = %s", size, sign ? "true" : "false", alias ? alias : "none");
+
+    if (!alias) {
+        switch (s_size) {
+            case 1:
+                *output_ffi_type = &ffi_type_sint8;
+                return 'B';
+            case 2:
+                *output_ffi_type = &ffi_type_sint16;
+                return 'S';
+            case 4:
+                *output_ffi_type = &ffi_type_sint32;
+                return 'I';
+            case 8:
+                *output_ffi_type = &ffi_type_sint64;
+                return 'J';
+            case -1:
+                *output_ffi_type = &ffi_type_uint8;
+                return 'b';
+            case -2:
+                *output_ffi_type = &ffi_type_uint16;
+                return 's';
+            case -4:
+                *output_ffi_type = &ffi_type_uint32;
+                return 'i';
+            case -8:
+                *output_ffi_type = &ffi_type_uint64;
+                return 'j';
+            default:
+                LOG_ERROR("Unrecognized size = %d", size);
+                return '0';
+        }
+    
+    }
+    else {
+        if (strcmp(alias, "float") == 0) {
+            *output_ffi_type = &ffi_type_float;
+            return 'F';
+        }
+        else if (strcmp(alias, "double") == 0) {
+            *output_ffi_type = &ffi_type_double;
+            return 'D';
+        }
+        else if (strcmp(alias, "string") == 0) {
+            *output_ffi_type = &ffi_type_pointer;
+            return 't';
+        }
+        else if (strcmp(alias, "boolean") == 0) {
+            *output_ffi_type = &ffi_type_uint8;
+            return 'Z';
+        }
+        else if (strcmp(alias, "void") == 0) {
+            *output_ffi_type = &ffi_type_void;
+            return 'V';
+        }
+        else if (strcmp(alias, "void_ptr") == 0) {
+            *output_ffi_type = &ffi_type_pointer;
+            return 'P';
+        }
+        else if (strcmp(alias, "native_int") == 0) {
+            *output_ffi_type = &ffi_type_sint;
+            return 'N';
+        }
+        else {
+            LOG_ERROR("Unrecognized alias = %s", alias);
+            return '0';
+        }
+    }
+}
+
+static char * dynAvprType_createFqnFromJson(json_t const * const jsonObject, const char * namespace) {
+    const char *name = json_string_value(json_object_get(jsonObject, "name"));
+    if (!name) {
+        LOG_ERROR("This object appears to not have a name!!");
+        return NULL;
+    }
+
+    const bool local_ns = json_is_string(json_object_get(jsonObject, "namespace"));
+    const char *ns =  local_ns ? json_string_value(json_object_get(jsonObject, "namespace")) : namespace;
+    if (!ns) {
+        LOG_ERROR("Need a namespace because the jsonObject does not have a namespace!");
+        return NULL;
+    }
+
+    // Create fqn
+    const int length = strlen(ns) + strlen(name) + 2;
+    char * fqn = calloc(length, sizeof(char));
+
+    snprintf(fqn, length, "%s.%s", ns, name);
+    return fqn;
+}
+
+static inline enum JsonTypeType dynAvprType_getType(json_t const * const json_type) {
+    if (json_is_string(json_type)) {
+        return SIMPLE;
+    }
+    else if (json_is_object(json_type) && json_is_string(json_object_get(json_type, "type")) && 0 == strcmp("array", json_string_value(json_object_get(json_type, "type")))) {
+        return ARRAY;
+    }
+    else {
+        return INVALID;
+    }
+}
+
+static inline void dynAvprType_createVersionMetaEntry(dyn_type * type, json_t const * const root, json_t const * const array_object, const char* parent_ns) {
+    struct meta_entry * m_entry = dynAvprType_createMetaEntry("version");
+
+    json_t const * json_type_version = json_object_get(dynAvprType_findType(dynType_getName(type), array_object, parent_ns), "version");
+
+    // If version is not available check root version
+    if (!json_is_string(json_type_version)) {
+        json_type_version = json_object_get(root, "version");
+    }
+
+    // If version is available use it (either from record or root)
+    if (json_is_string(json_type_version)) {
+        const char* version_str = json_string_value(json_type_version);
+        // Check if a valid version was given
+        version_pt v = NULL;
+        celix_status_t status = version_createVersionFromString(version_str, &v);
+        if (CELIX_SUCCESS == status) {
+            m_entry->value = strndup(version_str, STR_LENGTH);
+            version_destroy(v);
+        }
+        else {
+            m_entry->value = strndup("0.0.0", STR_LENGTH);
+            LOG_WARNING("parseAvpr: Did not find valid version, set version to 0.0.0");
+        }
+    }
+    else {
+        // If no version or an invalid version is available, default to 0.0.0
+        m_entry->value = strndup("0.0.0", STR_LENGTH);
+        LOG_WARNING("parseAvpr: Did not find version entry, set version to 0.0.0");
+    }
+
+    // Insert into type
+    TAILQ_INSERT_TAIL(&type->metaProperties, m_entry, entries);
+}
+
+static inline void dynAvprType_createAnnotationEntries(dyn_type * type, json_t const * const array_object, const char* parent_ns) {
+    json_t const * json_type = dynAvprType_findType(dynType_getName(type), array_object, parent_ns);
+    const char* const not_of_interest[5] = {"type", "name", "fields", "version", "alias"};
+    const char* key;
+    json_t const * value;
+    json_object_foreach((json_t*)json_type, key, value) {
+        if (! ( strcmp(key, not_of_interest[0]) == 0
+             || strcmp(key, not_of_interest[1]) == 0
+             || strcmp(key, not_of_interest[2]) == 0
+             || strcmp(key, not_of_interest[3]) == 0
+             || strcmp(key, not_of_interest[4]) == 0))
+        {
+            struct meta_entry * m_entry = dynAvprType_createMetaEntry(key);
+
+            switch (json_typeof(value)) {
+                case JSON_STRING:
+                    m_entry->value = strndup(json_string_value(value), STR_LENGTH);
+                    break;
+                case JSON_INTEGER:
+                    asprintf(&m_entry->value, "%" JSON_INTEGER_FORMAT, json_integer_value(value));
+                    break;
+                case JSON_REAL:
+                    asprintf(&m_entry->value, "%f", json_real_value(value));
+                    break;
+                case JSON_TRUE:
+                    m_entry->value = strdup("true");
+                    break;
+                case JSON_FALSE:
+                    m_entry->value = strdup("false");
+                    break;
+                case JSON_NULL:
+                    m_entry->value = strdup("null");
+                    break;
+                case JSON_OBJECT:
+                    /* fall through */
+                case JSON_ARRAY:
+                    /* fall through */
+                default:
+                    LOG_WARNING("createAnnotationEntries: encountered an annotation of an unknown type : %s", key);
+                    free(m_entry->name);
+                    free(m_entry);
+                    continue; // Do not add the invalid entry as a meta-entry
+            }
+
+            TAILQ_INSERT_TAIL(&type->metaProperties, m_entry, entries);
+        }
+    }
+}
diff --git a/libs/dfi/src/dyn_function.c b/libs/dfi/src/dyn_function.c
index db718f2..b70239b 100644
--- a/libs/dfi/src/dyn_function.c
+++ b/libs/dfi/src/dyn_function.c
@@ -17,37 +17,12 @@
  *under the License.
  */
 #include "dyn_function.h"
+#include "dyn_function_common.h"
 
 #include <strings.h>
 #include <stdlib.h>
 #include <ffi.h>
 
-#include "dyn_common.h"
-
-struct _dyn_function_type {
-    char *name;
-    struct types_head *refTypes; //NOTE not owned
-    TAILQ_HEAD(,_dyn_function_argument_type) arguments;
-    ffi_type **ffiArguments;
-    dyn_type *funcReturn;
-    ffi_cif cif;
-
-    //closure part
-    ffi_closure *ffiClosure;
-    void (*fn)(void);
-    void *userData;
-    void (*bind)(void *userData, void *args[], void *ret);
-};
-
-typedef struct _dyn_function_argument_type dyn_function_argument_type;
-struct _dyn_function_argument_type {
-    int index;
-    char *name;
-    enum dyn_function_argument_meta argumentMeta;
-    dyn_type *type;
-    TAILQ_ENTRY(_dyn_function_argument_type) entries;
-};
-
 static const int OK = 0;
 static const int MEM_ERROR = 1;
 static const int PARSE_ERROR = 2;
@@ -59,7 +34,7 @@ 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);
 
-extern ffi_type * dynType_ffiType(dyn_type *type);
+ffi_type * dynType_ffiType(dyn_type *type);
 
 int dynFunction_parse(FILE *descriptor, struct types_head *refTypes, dyn_function_type **out) {
     int status = OK;
diff --git a/libs/dfi/src/dyn_interface.c b/libs/dfi/src/dyn_interface.c
index abb5345..2e9581a 100644
--- a/libs/dfi/src/dyn_interface.c
+++ b/libs/dfi/src/dyn_interface.c
@@ -23,28 +23,22 @@
 
 #include "dyn_common.h"
 #include "dyn_type.h"
-#include "dyn_interface.h"
+#include "dyn_interface_common.h"
 
 DFI_SETUP_LOG(dynInterface);
 
-struct _dyn_interface_type {
-    struct namvals_head header;
-    struct namvals_head annotations;
-    struct types_head types;
-    struct methods_head methods;
-    version_pt version;
-};
-
 static const int OK = 0;
 static const int ERROR = 1;
 
+// Also export for dyn_avpr_interface
+int dynInterface_checkInterface(dyn_interface_type *intf);
+
 static int dynInterface_parseSection(dyn_interface_type *intf, FILE *stream);
 static int dynInterface_parseAnnotations(dyn_interface_type *intf, FILE *stream);
 static int dynInterface_parseTypes(dyn_interface_type *intf, FILE *stream);
 static int dynInterface_parseMethods(dyn_interface_type *intf, FILE *stream);
 static int dynInterface_parseHeader(dyn_interface_type *intf, FILE *stream);
 static int dynInterface_parseNameValueSection(dyn_interface_type *intf, FILE *stream, struct namvals_head *head);
-static int dynInterface_checkInterface(dyn_interface_type *intf);
 static int dynInterface_getEntryForHead(struct namvals_head *head, const char *name, char **value);
 
 int dynInterface_parse(FILE *descriptor, dyn_interface_type **out) {
@@ -99,7 +93,7 @@ int dynInterface_parse(FILE *descriptor, dyn_interface_type **out) {
     return status;
 }
 
-static int dynInterface_checkInterface(dyn_interface_type *intf) {
+int dynInterface_checkInterface(dyn_interface_type *intf) {
     int status = OK;
 
     //check header section
diff --git a/libs/dfi/src/dyn_type.c b/libs/dfi/src/dyn_type.c
index 4fc79ff..b223ca6 100644
--- a/libs/dfi/src/dyn_type.c
+++ b/libs/dfi/src/dyn_type.c
@@ -24,10 +24,16 @@
 #include <errno.h>
 #include <ffi.h>
 
+#include "dyn_type_common.h"
 #include "dyn_common.h"
 
 DFI_SETUP_LOG(dynType)
 
+static const int OK = 0;
+static const int ERROR = 1;
+static const int MEM_ERROR = 2;
+static const int PARSE_ERROR = 3;
+
 static int dynType_parseWithStream(FILE *stream, const char *name, dyn_type *parent, struct types_head *refTypes, dyn_type **result);
 static void dynType_clear(dyn_type *type);
 static void dynType_clearComplex(dyn_type *type);
@@ -38,7 +44,6 @@ ffi_type * dynType_ffiType(dyn_type *type);
 static struct type_entry *dynType_allocTypeEntry(void);
 
 static ffi_type * dynType_ffiTypeFor(int c);
-static dyn_type * dynType_findType(dyn_type *type, char *name);
 static int dynType_parseAny(FILE *stream, dyn_type *type);
 static int dynType_parseComplex(FILE *stream, dyn_type *type);
 static int dynType_parseNestedType(FILE *stream, dyn_type *type);
@@ -47,13 +52,13 @@ static int dynType_parseRefByValue(FILE *stream, dyn_type *type);
 static int dynType_parseSequence(FILE *stream, dyn_type *type);
 static int dynType_parseSimple(int c, dyn_type *type);
 static int dynType_parseTypedPointer(FILE *stream, dyn_type *type);
-static void dynType_prepCif(ffi_type *type);
 static unsigned short dynType_getOffset(dyn_type *type, int index);
 
 static void dynType_printAny(char *name, dyn_type *type, int depth, FILE *stream);
 static void dynType_printComplex(char *name, dyn_type *type, int depth, FILE *stream);
 static void dynType_printSequence(char *name, dyn_type *type, int depth, FILE *stream);
 static void dynType_printSimple(char *name, dyn_type *type, int depth, FILE *stream);
+static void dynType_printEnum(char *name, dyn_type *type, int depth, FILE *stream);
 static void dynType_printTypedPointer(char *name, dyn_type *type, int depth, FILE *stream);
 static void dynType_printDepth(int depth, FILE *stream);
 
@@ -62,6 +67,7 @@ static void dynType_printComplexType(dyn_type *type, FILE *stream);
 static void dynType_printSimpleType(dyn_type *type, FILE *stream);
 
 static int dynType_parseText(FILE *stream, dyn_type *type);
+static int dynType_parseEnum(FILE *stream, dyn_type *type);
 void dynType_freeComplexType(dyn_type *type, void *loc);
 void dynType_deepFree(dyn_type *type, void *loc, bool alsoDeleteSelf);
 void dynType_freeSequenceType(dyn_type *type, void *seqLoc);
@@ -74,47 +80,6 @@ struct generic_sequence {
     void *buf;
 };
 
-TAILQ_HEAD(meta_properties_head, meta_entry);
-struct meta_entry {
-    char *name;
-    char *value;
-    TAILQ_ENTRY(meta_entry) entries;
-};
-
-
-struct _dyn_type {
-    char *name;
-    char descriptor;
-    int type;
-    ffi_type *ffiType;
-    dyn_type *parent;
-    struct types_head *referenceTypes; //NOTE: not owned
-    struct types_head nestedTypesHead;
-    struct meta_properties_head metaProperties;
-    union {
-        struct {
-            struct complex_type_entries_head entriesHead;
-            ffi_type structType; //dyn_type.ffiType points to this
-            dyn_type **types; //based on entriesHead for fast access
-        } complex;
-        struct {
-            ffi_type seqType; //dyn_type.ffiType points to this
-            dyn_type *itemType;
-        } sequence;
-        struct {
-            dyn_type *typedType;
-        } typedPointer;
-        struct {
-            dyn_type *ref;
-        } ref;
-    };
-};
-
-static const int OK = 0;
-static const int ERROR = 1;
-static const int MEM_ERROR = 2;
-static const int PARSE_ERROR = 3;
-
 int dynType_parse(FILE *descriptorStream, const char *name, struct types_head *refTypes, dyn_type **type) {
     return dynType_parseWithStream(descriptorStream, name, NULL, refTypes, type);
 }
@@ -199,6 +164,9 @@ static int dynType_parseAny(FILE *stream, dyn_type *type) {
         case 't' :
             status = dynType_parseText(stream, type);
             break;
+        case 'E' :
+            status = dynType_parseEnum(stream, type);
+            break;
         case '#' :
             status = dynType_parseMetaInfo(stream, type);
             if (status == OK) {
@@ -261,6 +229,14 @@ static int dynType_parseText(FILE *stream, dyn_type *type) {
     return status;
 }
 
+static int dynType_parseEnum(FILE *stream, dyn_type *type) {
+    int status = OK;
+    type->ffiType = &ffi_type_sint32;
+    type->descriptor = 'E';
+    type->type = DYN_TYPE_SIMPLE;
+    return status;
+}
+
 static int dynType_parseComplex(FILE *stream, dyn_type *type) {
     int status = OK;
     type->type = DYN_TYPE_COMPLEX;
@@ -296,7 +272,7 @@ static int dynType_parseComplex(FILE *stream, dyn_type *type) {
         c = fgetc(stream);
     }
 
-
+// loop over names
     if (status == OK) {
         entry = TAILQ_FIRST(&type->complex.entriesHead);
         char *name = NULL;
@@ -508,13 +484,6 @@ static int dynType_parseTypedPointer(FILE *stream, dyn_type *type) {
     return status;
 }
 
-static void dynType_prepCif(ffi_type *type) {
-    ffi_cif cif;
-    ffi_type *args[1];
-    args[0] = type;
-    ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_uint, args);
-}
-
 void dynType_destroy(dyn_type *type) {
     if (type != NULL) {          
         dynType_clear(type);
@@ -824,7 +793,6 @@ void dynType_simple_setValue(dyn_type *type, void *inst, void *in) {
     memcpy(inst, in, size);
 }
 
-
 int dynType_descriptorType(dyn_type *type) {
     return type->descriptor;
 }
@@ -842,15 +810,13 @@ const char * dynType_getMetaInfo(dyn_type *type, const char *name) {
     return result;
 }
 
-ffi_type *dynType_ffiType(dyn_type *type) {
-    if (type->type == DYN_TYPE_REF) {
-        if (type->ref.ref == NULL) {
-            LOG_ERROR("Error. Ref for %s is not (yet) initialized", type->name);
-            return NULL;
-        }
-        return type->ref.ref->ffiType;
-    }
-    return type->ffiType;
+int dynType_metaEntries(dyn_type *type, struct meta_properties_head **entries) {
+    *entries = &type->metaProperties;
+    return OK;
+}
+
+const char * dynType_getName(dyn_type *type) {
+    return type->name;
 }
 
 static ffi_type * dynType_ffiTypeFor(int c) {
@@ -887,7 +853,7 @@ static ffi_type * dynType_ffiTypeFor(int c) {
             type = &ffi_type_sint64;
             break;
         case 'j' :
-            type = &ffi_type_sint64;
+            type = &ffi_type_uint64;
             break;
         case 'N' :
             type = &ffi_type_sint;
@@ -902,38 +868,6 @@ static ffi_type * dynType_ffiTypeFor(int c) {
     return type;
 }
 
-static dyn_type * dynType_findType(dyn_type *type, char *name) {
-    dyn_type *result = NULL;
-
-    struct type_entry *entry = NULL;
-    if (type->referenceTypes != NULL) {
-        TAILQ_FOREACH(entry, type->referenceTypes, entries) {
-            LOG_DEBUG("checking ref type '%s' with name '%s'", entry->type->name, name);
-            if (strcmp(name, entry->type->name) == 0) {
-                result = entry->type;
-                break;
-            }
-        }
-    }
-
-    if (result == NULL) {
-        struct type_entry *nEntry = NULL;
-        TAILQ_FOREACH(nEntry, &type->nestedTypesHead, entries) {
-            LOG_DEBUG("checking nested type '%s' with name '%s'", nEntry->type->name, name);
-            if (strcmp(name, nEntry->type->name) == 0) {
-                result = nEntry->type;
-                break;
-            }
-        }
-    }
-
-    if (result == NULL && type->parent != NULL) {
-        result = dynType_findType(type->parent, name);
-    }
-
-    return result;
-}
-
 static unsigned short dynType_getOffset(dyn_type *type, int index) {
     assert(type->type == DYN_TYPE_COMPLEX);
     unsigned short offset = 0;
@@ -1037,7 +971,7 @@ static void dynType_printAny(char *name, dyn_type *type, int depth, FILE *stream
             dynType_printTypedPointer(name, toPrint, depth, stream);
             break;
         default :
-            fprintf(stream, "TODO Unsupported type %i\n", toPrint->type);
+            fprintf(stream, "TODO Unsupported type %d\n", toPrint->type);
             break;
     }
 }
@@ -1076,8 +1010,23 @@ static void dynType_printSequence(char *name, dyn_type *type, int depth, FILE *s
 }
 
 static void dynType_printSimple(char *name, dyn_type *type, int depth, FILE *stream) {
+    if (type->descriptor != 'E') {
+        dynType_printDepth(depth, stream);
+        fprintf(stream, "%s: simple type, size is %zu, alignment is %i, descriptor is '%c'.\n", name, type->ffiType->size, type->ffiType->alignment, type->descriptor);
+    }
+    else {
+        dynType_printEnum(name, type, depth, stream);
+    }
+}
+
+static void dynType_printEnum(char *name, dyn_type *type, int depth, FILE *stream) {
     dynType_printDepth(depth, stream);
-    fprintf(stream, "%s: simple type, size is %zu, alignment is %i, descriptor is '%c'.\n", name, type->ffiType->size, type->ffiType->alignment, type->descriptor);
+    fprintf(stream, "%s: enum type, size is %zu, alignment is %i, descriptor is '%c'. values:", name, type->ffiType->size, type->ffiType->alignment, type->descriptor);
+    struct meta_entry * m_entry;
+    TAILQ_FOREACH(m_entry, &type->metaProperties, entries) {
+        fprintf(stream, " (\"%s\":\"%s\")", m_entry->name, m_entry->value);
+    }
+    fprintf(stream, "\n");
 }
 
 static void dynType_printTypedPointer(char *name, dyn_type *type, int depth, FILE *stream) {
diff --git a/libs/dfi/src/dyn_type_common.c b/libs/dfi/src/dyn_type_common.c
new file mode 100644
index 0000000..b3ad7c3
--- /dev/null
+++ b/libs/dfi/src/dyn_type_common.c
@@ -0,0 +1,81 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include "dyn_type.h"
+
+#include "dyn_type_common.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <ffi.h>
+
+DFI_SETUP_LOG(dynTypeCommon)
+
+dyn_type * dynType_findType(dyn_type *type, char *name) {
+    dyn_type *result = NULL;
+
+    struct type_entry *entry = NULL;
+    if (type->referenceTypes != NULL) {
+        TAILQ_FOREACH(entry, type->referenceTypes, entries) {
+            LOG_DEBUG("checking ref type '%s' with name '%s'", entry->type->name, name);
+            if (strcmp(name, entry->type->name) == 0) {
+                result = entry->type;
+                break;
+            }
+        }
+    }
+
+    if (result == NULL) {
+        struct type_entry *nEntry = NULL;
+        TAILQ_FOREACH(nEntry, &type->nestedTypesHead, entries) {
+            LOG_DEBUG("checking nested type '%s' with name '%s'", nEntry->type->name, name);
+            if (strcmp(name, nEntry->type->name) == 0) {
+                result = nEntry->type;
+                break;
+            }
+        }
+    }
+
+    if (result == NULL && type->parent != NULL) {
+        result = dynType_findType(type->parent, name);
+    }
+
+    return result;
+}
+
+ffi_type * dynType_ffiType(dyn_type * type) {
+    if (type->type == DYN_TYPE_REF) {
+        if (type->ref.ref == NULL) {
+            LOG_ERROR("Error. Ref for %s is not (yet) initialized", type->name);
+            return NULL;
+        }
+        return type->ref.ref->ffiType;
+    }
+    return type->ffiType;
+}
+
+void dynType_prepCif(ffi_type *type) {
+    ffi_cif cif;
+    ffi_type *args[1];
+    args[0] = type;
+    ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_uint, args);
+}
+
diff --git a/libs/dfi/src/json_serializer.c b/libs/dfi/src/json_serializer.c
index 106c745..c3307c4 100644
--- a/libs/dfi/src/json_serializer.c
+++ b/libs/dfi/src/json_serializer.c
@@ -18,6 +18,7 @@
  */
 #include "json_serializer.h"
 #include "dyn_type.h"
+#include "dyn_type_common.h"
 #include "dyn_interface.h"
 
 #include <jansson.h>
@@ -30,12 +31,13 @@ static int jsonSerializer_parseObject(dyn_type *type, json_t *object, void *inst
 static int jsonSerializer_parseObjectMember(dyn_type *type, const char *name, json_t *val, void *inst);
 static int jsonSerializer_parseSequence(dyn_type *seq, json_t *array, void *seqLoc);
 static int jsonSerializer_parseAny(dyn_type *type, void *input, json_t *val);
+static int jsonSerializer_parseEnum(dyn_type *type, const char* enum_name, int32_t *out);
 
 static int jsonSerializer_writeAny(dyn_type *type, void *input, json_t **val);
-
 static int jsonSerializer_writeComplex(dyn_type *type, void *input, json_t **val);
-
 static int jsonSerializer_writeSequence(dyn_type *type, void *input, json_t **out);
+static int jsonSerializer_writeEnum(dyn_type *type, int32_t enum_value, json_t **out);
+
 
 static int OK = 0;
 static int ERROR = 1;
@@ -159,6 +161,7 @@ static int jsonSerializer_parseAny(dyn_type *type, void *loc, json_t *val) {
     int *n;             //N
     int16_t *s;         //S
     int32_t *i;         //I
+    int32_t *E;         //E
     int64_t *l;         //J
     uint8_t   *ub;      //b
     uint16_t  *us;      //s
@@ -214,6 +217,17 @@ static int jsonSerializer_parseAny(dyn_type *type, void *loc, json_t *val) {
             ul = loc;
             *ul = (uint64_t) json_integer_value(val);
             break;
+        case 'E' :
+            if (json_is_null(val)) {
+                //nop
+            } else if (json_is_string(val)){
+                E = loc;
+                status = jsonSerializer_parseEnum(type, json_string_value(val), E);
+            } else {
+                status = ERROR;
+                LOG_ERROR("Expected json string for enum type but got %i", json_typeof(val));
+            }
+            break;
         case 't' :
             if (json_is_null(val)) {
                 //nop
@@ -299,6 +313,20 @@ int jsonSerializer_serialize(dyn_type *type, const void* input, char **output) {
     return status;
 }
 
+static int jsonSerializer_parseEnum(dyn_type *type, const char* enum_name, int32_t *out) {
+    struct meta_entry * entry;
+
+    TAILQ_FOREACH(entry, &type->metaProperties, entries) {
+        if (0 == strcmp(enum_name, entry->name)) {
+            *out = atoi(entry->value);
+            return OK;
+        }
+    }
+
+    LOG_ERROR("Could not find Enum value %s in enum type", enum_name);
+    return ERROR;
+}
+
 int jsonSerializer_serializeJson(dyn_type *type, const void* input, json_t **out) {
     return jsonSerializer_writeAny(type, (void*)input /*TODO update static function to take const void**/, out);
 }
@@ -317,6 +345,7 @@ static int jsonSerializer_writeAny(dyn_type *type, void* input, json_t **out) {
     int *n;             //N
     int16_t *s;         //S
     int32_t *i;         //I
+    int32_t *e;         //E
     int64_t *l;         //J
     uint8_t   *ub;      //b
     uint16_t  *us;      //s
@@ -375,6 +404,10 @@ static int jsonSerializer_writeAny(dyn_type *type, void* input, json_t **out) {
         case 't' :
             val = json_string(*(const char **) input);
             break;
+        case 'E':
+            e = input;
+            jsonSerializer_writeEnum(type, *e, &val);
+            break;
         case '*' :
             status = dynType_typedPointer_getTypedType(type, &subType);
             if (status == OK) {
@@ -454,11 +487,11 @@ static int jsonSerializer_writeComplex(dyn_type *type, void *input, json_t **out
             dyn_type *subType = NULL;
             index = dynType_complex_indexForName(type, entry->name);
             if (index < 0) {
-		LOG_ERROR("Cannot find index for member '%s'", entry->name);
+                LOG_ERROR("Cannot find index for member '%s'", entry->name);
                 status = ERROR;
             }
             if(status == OK){
-		status = dynType_complex_valLocAt(type, index, input, &subLoc);
+                status = dynType_complex_valLocAt(type, index, input, &subLoc);
             }
             if (status == OK) {
                 status = dynType_complex_dynTypeAt(type, index, &subType);
@@ -484,3 +517,21 @@ static int jsonSerializer_writeComplex(dyn_type *type, void *input, json_t **out
     return status;
 }
 
+static int jsonSerializer_writeEnum(dyn_type *type, int32_t enum_value, json_t **out) {
+    struct meta_entry * entry;
+
+    // Convert to string
+    char enum_value_str[32];
+    snprintf(enum_value_str, 32, "%d", enum_value);
+
+    // Lookup in meta-information
+    TAILQ_FOREACH(entry, &type->metaProperties, entries) {
+        if (0 == strcmp(enum_value_str, entry->value)) {
+            *out = json_string((const char*)entry->name);
+            return OK;
+        }
+    }
+
+    LOG_ERROR("Could not find Enum value %s in enum type", enum_value_str);
+    return ERROR;
+}
diff --git a/libs/dfi/test/avro_descriptor_translator_tests.cpp b/libs/dfi/test/avro_descriptor_translator_tests.cpp
index 5bab518..23149e1 100644
--- a/libs/dfi/test/avro_descriptor_translator_tests.cpp
+++ b/libs/dfi/test/avro_descriptor_translator_tests.cpp
@@ -178,3 +178,4 @@ TEST(AvroDescTranslatorTest, invalid1) {
 TEST(AvroDescTranslatorTest, invalid2) {
     invalid("schemas/invalid2.avpr");
 }
+
diff --git a/libs/dfi/test/dyn_avpr_function_tests.cpp b/libs/dfi/test/dyn_avpr_function_tests.cpp
new file mode 100644
index 0000000..e9172fd
--- /dev/null
+++ b/libs/dfi/test/dyn_avpr_function_tests.cpp
@@ -0,0 +1,620 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <CppUTest/TestHarness.h>
+#include "CppUTest/CommandLineTestRunner.h"
+
+extern "C" {
+    #include <stdio.h>
+    #include <stdint.h>
+    #include <stdlib.h>
+    #include <string.h>
+    #include <ctype.h>
+    #include <stdarg.h>
+
+    #include "dyn_common.h"
+    #include "dyn_function.h"
+
+    static void stdLog(void*, int level, const char *file, int line, const char *msg, ...) {
+        va_list ap;
+        const char *levels[5] = {"NIL", "ERROR", "WARNING", "INFO", "DEBUG"};
+        fprintf(stderr, "%s: FILE:%s, LINE:%i, MSG:",levels[level], file, line);
+        va_start(ap, msg);
+        vfprintf(stderr, msg, ap);
+        fprintf(stderr, "\n");
+        va_end(ap);
+    }
+}
+
+const char* theAvprFile = "{ \
+                \"protocol\" : \"types\", \
+                \"namespace\" : \"test.dt\", \
+                \"version\" : \"1.0.0\", \
+                \"types\" : [ { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Void\", \
+                    \"alias\" : \"void\", \
+                    \"size\" : 4 \
+                  }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"VoidPtr\", \
+                    \"alias\" : \"void_ptr\", \
+                    \"size\" : 4 \
+                  }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Sint\", \
+                    \"size\" : 4, \
+                    \"signed\" : true \
+                  }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"NativeInt\", \
+                    \"size\" : 4, \
+                    \"alias\" : \"native_int\" \
+                  }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"String\", \
+                    \"alias\" : \"string\", \
+                    \"size\" : 8 \
+                  }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Double\", \
+                    \"alias\" : \"double\", \
+                    \"size\" : 8 \
+                  }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"StructString\", \
+                    \"fields\" : [ { \
+                          \"name\" : \"name\", \
+                          \"type\" : \"String\" \
+                        } , { \
+                          \"name\" : \"id\", \
+                          \"type\" : \"Sint\" \
+                    } ] \
+                  }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"AStruct\", \
+                    \"namespace\" : \"nested.test.dt\", \
+                    \"fields\" : [ { \
+                          \"name\" : \"val1\", \
+                          \"type\" : \"test.dt.Sint\" \
+                        } , { \
+                          \"name\" : \"val2\", \
+                          \"type\" : \"test.dt.Sint\" \
+                        } , { \
+                          \"name\" : \"val3\", \
+                          \"type\" : \"test.dt.Double\" \
+                    } ] \
+                  }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"MArray\", \
+                    \"fields\" : [ { \
+                          \"name\" : \"array\", \
+                          \"type\" : { \
+                            \"type\" : \"array\",\
+                            \"items\" : \"Double\"\
+                          } \
+                    } ] \
+                  } ] ,\
+                \"messages\" : { \
+                    \"simpleFunc\" : {\
+                        \"request\" : [ {\
+                                \"name\" : \"arg1\", \
+                                \"type\" : \"Sint\" \
+                            } , { \
+                                \"name\" : \"arg2\", \
+                                \"type\" : \"Sint\" \
+                            } , { \
+                                \"name\" : \"arg3\", \
+                                \"type\" : \"Sint\" \
+                            } ],\
+                        \"response\" : \"Sint\" \
+                    }, \
+                    \"structFunc\" : {\
+                        \"namespace\" : \"nested.test.dt\", \
+                        \"request\" : [ {\
+                                \"name\" : \"arg1\", \
+                                \"type\" : \"test.dt.Sint\" \
+                            } , { \
+                                \"name\" : \"arg2\", \
+                                \"type\" : \"AStruct\" \
+                            } , { \
+                                \"name\" : \"arg3\", \
+                                \"type\" : \"test.dt.Double\" \
+                            } ],\
+                        \"response\" : \"test.dt.Double\" \
+                    }, \
+                    \"accessFunc\" : {\
+                        \"request\" : [ {\
+                                \"name\" : \"arg1\", \
+                                \"type\" : \"Double\" \
+                            } , { \
+                                \"name\" : \"arg2\", \
+                                \"type\" : \"nested.test.dt.AStruct\" \
+                            } , { \
+                                \"name\" : \"arg3\", \
+                                \"type\" : \"Double\" \
+                            } ],\
+                        \"response\" : \"test.dt.Void\" \
+                    }, \
+                    \"outFunc\" : {\
+                        \"request\" : [ {\
+                                \"name\" : \"arg1\", \
+                                \"type\" : \"VoidPtr\" \
+                            } , { \
+                                \"name\" : \"arg2\", \
+                                \"type\" : \"Double\" \
+                            } , { \
+                                \"name\" : \"arg3\", \
+                                \"type\" : \"Double\", \
+                                \"ptr\" : true \
+                            } ],\
+                        \"response\" : \"NativeInt\" \
+                    }, \
+                    \"seqFunc\" : {\
+                        \"request\" : [ {\
+                                \"name\" : \"arg1\", \
+                                \"type\" : \"MArray\" \
+                            } ],\
+                        \"response\" : \"Void\" \
+                    }, \
+                    \"infoFunc\" : {\
+                        \"request\" : [ {\
+                                \"name\" : \"arg1\", \
+                                \"type\" : \"Sint\" \
+                            } ],\
+                        \"response\" : \"Double\" \
+                    }, \
+                    \"arrayInFunc\" : {\
+                        \"request\" : [ {\
+                                \"name\" : \"arg1\", \
+                                \"type\" : { \
+                                  \"type\" : \"array\",\
+                                  \"items\" : \"Double\" \
+                                } \
+                            } ],\
+                        \"response\" : \"Double\" \
+                    }, \
+                    \"arrayOutFunc\" : {\
+                        \"request\" : [ {\
+                                \"name\" : \"arg1\", \
+                                \"type\" : \"Double\" \
+                            } ],\
+                        \"response\" : { \
+                              \"type\" : \"array\",\
+                              \"items\" : \"Double\" \
+                            } \
+                    }, \
+                    \"stringOutFunc\" : {\
+                        \"request\" : [ ],\
+                        \"response\" : \"String\" \
+                    }, \
+                    \"structStringOutFunc\" : {\
+                        \"request\" : [ ],\
+                        \"response\" : \"StructString\" \
+                    } \
+                }\
+                }";
+
+TEST_GROUP(DynAvprFunctionTests) {
+    void setup() override {
+        int lvl = 1;
+        dynAvprFunction_logSetup(stdLog, nullptr, lvl);
+        dynAvprType_logSetup(stdLog, nullptr, lvl);
+    }
+};
+
+// Test 1, simple function with three arguments and a return type
+static int avpr_example1(__attribute__((unused)) void* handle, int32_t a, int32_t b, int32_t c, int32_t * out) {
+    CHECK_EQUAL(2, a);
+    CHECK_EQUAL(4, b);
+    CHECK_EQUAL(8, c);
+    *out = 1;
+    return 0;
+}
+
+TEST(DynAvprFunctionTests, Example1) {
+    auto fp = (void (*)()) avpr_example1;
+    dyn_function_type * dynFunc = dynFunction_parseAvprWithStr(theAvprFile, "test.dt.simpleFunc");
+    CHECK(dynFunc != nullptr);
+
+    int handle = 0;
+    int* handle_ptr = &handle;
+    int32_t a = 2;
+    int32_t b = 4;
+    int32_t c = 8;
+    int32_t out = 0;
+    int32_t * p_out = &out;
+    void *values[5];
+    values[0] = &handle_ptr;
+    values[1] = &a;
+    values[2] = &b;
+    values[3] = &c;
+    values[4] = &p_out;
+    int rVal = 1;
+
+    int rc = dynFunction_call(dynFunc, fp, &rVal, values);
+    CHECK_EQUAL(0, rc);
+    CHECK_EQUAL(1, out);
+    CHECK_EQUAL(0, rVal);
+    dynFunction_destroy(dynFunc);
+}
+
+
+// Test 2, function with complex argument
+struct avpr_example2_arg2 {
+    int32_t val1;
+    int32_t val2;
+    double val3;
+};
+
+static int avpr_example2(__attribute__((unused)) void* handle, int32_t arg1, struct avpr_example2_arg2 arg2, double arg3, double* out) {
+    CHECK_EQUAL(2, arg1);
+    CHECK_EQUAL(2, arg2.val1);
+    CHECK_EQUAL(3, arg2.val2);
+    CHECK_EQUAL(4.1, arg2.val3);
+    CHECK_EQUAL(8.1, arg3);
+    *out = 2.2;
+    return 0;
+}
+
+TEST(DynAvprFunctionTests, Example2) {
+    auto fp = (void (*)()) avpr_example2;
+    dyn_function_type * dynFunc = dynFunction_parseAvprWithStr(theAvprFile, "nested.test.dt.structFunc");
+    CHECK(dynFunc != nullptr);
+
+    int handle = 0;
+    int* handle_ptr = &handle;
+    int32_t a = 2;
+    avpr_example2_arg2 arg2 {2, 3, 4.1};
+
+    double c = 8.1;
+    double out = 0.0;
+    double* p_out = &out;
+    void *values[5];
+    values[0] = &handle_ptr;
+    values[1] = &a;
+    values[2] = &arg2;
+    values[3] = &c;
+    values[4] = &p_out;
+    int rVal = 1;
+
+    int rc = dynFunction_call(dynFunc, fp, &rVal, values);
+    CHECK_EQUAL(0, rc);
+    CHECK_EQUAL(0, rVal);
+    CHECK_EQUAL(2.2, out);
+    dynFunction_destroy(dynFunc);
+}
+
+// Test 3, Test access of functions, see if arguments and result type can be accessed
+TEST(DynAvprFunctionTests, Example3) {
+    dyn_function_type * dynFunc = dynFunction_parseAvprWithStr(theAvprFile, "test.dt.accessFunc");
+    CHECK(dynFunc != nullptr);
+
+    int nrOfArgs = dynFunction_nrOfArguments(dynFunc);
+    CHECK_EQUAL(3+1+1, nrOfArgs);
+
+    dyn_type *arg1 = dynFunction_argumentTypeForIndex(dynFunc, 2);
+    CHECK(arg1 != nullptr);
+    CHECK_EQUAL('{', (char) dynType_descriptorType(arg1));
+
+    dyn_type *nonExist = dynFunction_argumentTypeForIndex(dynFunc, 10);
+    CHECK(nonExist == nullptr);
+
+    dyn_type *returnType = dynFunction_returnType(dynFunc);
+    CHECK_EQUAL('N', (char) dynType_descriptorType(returnType));
+
+    dynFunction_destroy(dynFunc);
+}
+
+
+// Test 4, with void pointer and native output
+/*
+static int avpr_example4(__attribute__((unused)) void *handle, void *ptr, double a, double *out, int *out_2) {
+    auto b = (double *)ptr;
+    CHECK_EQUAL(2.0, *b);
+    CHECK_EQUAL(2.0, a);
+    *out = *b * a; // => out parameter
+    *out_2 = 3;
+    return 0;
+}
+
+TEST(DynAvprFunctionTests, Example4) {
+    auto fp = (void(*)()) avpr_example4;
+    dyn_function_type * dynFunc = dynFunction_parseAvprWithStr(theAvprFile, "test.dt.outFunc");
+    CHECK(dynFunc != nullptr);
+
+    int handle = 0;
+    int* handle_ptr = &handle;
+    double result = -1.0;
+    double *input = &result;
+    double a = 2.0;
+    void *ptr = &a;
+    void *args[5];
+    int out = 0;
+    int* out_ptr = &out;
+    args[0] = &handle_ptr;
+    args[1] = &ptr;
+    args[2] = &a;
+    args[3] = &input;
+    args[4] = &out_ptr;
+    int rVal = 1;
+    int rc = dynFunction_call(dynFunc, fp, &rVal, args);
+
+    CHECK_EQUAL(0, rc);
+    CHECK_EQUAL(4.0, result);
+    CHECK_EQUAL(3, out);
+
+    auto inMemResult = (double *)calloc(1, sizeof(double));
+    a = 2.0;
+    ptr = &a;
+    args[1] = &ptr;
+    args[2] = &a;
+    args[3] = &inMemResult;
+    rVal = 0;
+    rc = dynFunction_call(dynFunc, fp, &rVal, args);
+    CHECK_EQUAL(0, rc);
+    CHECK_EQUAL(4.0, result);
+    free(inMemResult);
+    dynFunction_destroy(dynFunc);
+}
+*/
+
+// Test5, testing with sequence as argument
+struct tst_seq {
+    uint32_t cap;
+    uint32_t len;
+    double *buf;
+};
+
+static int avpr_example5(__attribute__((unused)) void* handle, struct tst_seq seq, __attribute__((unused)) void* out)  {
+    CHECK_EQUAL(4, seq.cap);
+    CHECK_EQUAL(2, seq.len);
+    CHECK_EQUAL(1.1, seq.buf[0]);
+    CHECK_EQUAL(2.2, seq.buf[1]);
+    return 0;
+}
+
+TEST(DynAvprFunctionTests, Example5) {
+    auto fp = (void(*)()) avpr_example5;
+    dyn_function_type * dynFunc = dynFunction_parseAvprWithStr(theAvprFile, "test.dt.seqFunc");
+
+    CHECK(dynFunc != nullptr);
+
+    int handle = 0;
+    int* handle_ptr = &handle;
+    double buf[4];
+    buf[0] = 1.1;
+    buf[1] = 2.2;
+    struct tst_seq seq {4, 2, buf};
+    int out = 0;
+    int* out_ptr = &out;
+
+    void *args[3];
+    args[0] = &handle_ptr;
+    args[1] = &seq;
+    args[2] = &out_ptr;
+    int retArg = 1;
+
+    int rc = dynFunction_call(dynFunc, fp, &retArg, args);
+    CHECK_EQUAL(0, rc);
+    CHECK_EQUAL(0, retArg);
+
+    dynFunction_destroy(dynFunc);
+}
+
+// Test 6, Test data accessible with handle
+struct info {
+    char * name;
+    int id;
+};
+
+static int avpr_example6(void *handle, int32_t id_modifier, double* out) {
+    auto fake_this = (struct info *) handle;
+    CHECK(fake_this != nullptr);
+    CHECK(fake_this->name != nullptr);
+    CHECK_EQUAL(0, strcmp(fake_this->name, "test_name"));
+    CHECK_EQUAL(42, fake_this->id);
+    *out = (double)(fake_this->id + id_modifier);
+    return 0;
+}
+
+TEST(DynAvprFunctionTests, Example6) {
+    auto fp = (void(*)()) avpr_example6;
+    dyn_function_type * dynFunc = dynFunction_parseAvprWithStr(theAvprFile, "test.dt.infoFunc");
+    CHECK(dynFunc != nullptr);
+
+    info handle {strdup("test_name"), 42};
+    CHECK(handle.name != nullptr);
+
+    struct info * handle_ptr = &handle;
+    int32_t argument = 58;
+    double out = 0.0;
+    double * out_ptr = &out;
+
+    void *values[3];
+    values[0] = &handle_ptr;
+    values[1] = &argument;
+    values[2] = &out_ptr;
+    int rVal = 1;
+
+    int rc = dynFunction_call(dynFunc, fp, &rVal, values);
+    CHECK_EQUAL(0, rc);
+    CHECK_EQUAL(100.0, out);
+    CHECK_EQUAL(0, rVal);
+    dynFunction_destroy(dynFunc);
+    free(handle.name);
+}
+
+//Test 7, Test function with array as parameter
+struct double_seq {
+    uint32_t cap;
+    uint32_t len;
+    double *buf;
+};
+
+static int avpr_example7(__attribute__((unused)) void *handle, struct double_seq seq_in, double* out) {
+    CHECK_EQUAL(2, seq_in.cap);
+    CHECK_EQUAL(2, seq_in.len);
+    *out = seq_in.buf[0] + seq_in.buf[1];
+    return 0;
+}
+
+TEST(DynAvprFunctionTests, Example7) {
+    auto fp = (void(*)()) avpr_example7;
+    dyn_function_type * dynFunc = dynFunction_parseAvprWithStr(theAvprFile, "test.dt.arrayInFunc");
+    CHECK(dynFunc != nullptr);
+
+    int handle = 0;
+    int* handle_ptr = &handle;
+
+    double buf[2];
+    buf[0] = 1.101;
+    buf[1] = 2.202;
+    double_seq s_seq {2, 2, buf};
+
+    double out = 0.0;
+    double *out_ptr = &out;
+
+    void *args[3];
+    args[0] = &handle_ptr;
+    args[1] = &s_seq;
+    args[2] = &out_ptr;
+    int rVal = 0;
+
+    int rc = dynFunction_call(dynFunc, fp, &rVal, args);
+    CHECK_EQUAL(0, rc);
+    DOUBLES_EQUAL(3.303, out, 0.00001);
+
+    dynFunction_destroy(dynFunc);
+}
+
+//Test 8, Test function with array as return value
+static int avpr_example8(__attribute__((unused))void *handle, double arg1, struct double_seq** out) {
+    DOUBLES_EQUAL(2.0, arg1, 0.0001);
+    CHECK_EQUAL(3, (*out)->cap);
+    (*out)->buf[0] = 0.0;
+    (*out)->buf[1] = 1.1;
+    (*out)->buf[2] = 2.2;
+    return 0;
+}
+
+TEST(DynAvprFunctionTests, Example8) {
+    auto fp = (void(*)()) avpr_example8;
+    dyn_function_type * dynFunc = dynFunction_parseAvprWithStr(theAvprFile, "test.dt.arrayOutFunc");
+    CHECK(dynFunc != nullptr);
+
+    int handle = 0;
+    int* handle_ptr = &handle;
+
+    double arg1 = 2.0;
+
+    double buf[3];
+    buf[0] = -1.1;
+    buf[1] = 0.0;
+    buf[2] = 0.0;
+    double_seq dseq {3, 3, buf};
+    struct double_seq * out_ptr = &dseq;
+    struct double_seq ** out_ptr_ptr = &out_ptr;
+
+    void *args[3];
+    args[0] = &handle_ptr;
+    args[1] = &arg1;
+    args[2] = &out_ptr_ptr;
+    int rVal = 0;
+
+    int rc = dynFunction_call(dynFunc, fp, &rVal, args);
+    CHECK_EQUAL(0, rc);
+    DOUBLES_EQUAL(0.0, buf[0], 0.0001);
+    DOUBLES_EQUAL(1.1, buf[1], 0.0001);
+    DOUBLES_EQUAL(2.2, buf[2], 0.0001);
+
+    dynFunction_destroy(dynFunc);
+}
+
+// Test 9, Test function with string as return value
+static int avpr_example9(__attribute__((unused))void *handle, char** out) {
+    *out = strdup("result_out");
+    CHECK(*out != nullptr);
+    return 0;
+}
+
+TEST(DynAvprFunctionTests, Example9) {
+    auto fp = (void(*)()) avpr_example9;
+    dyn_function_type * dynFunc = dynFunction_parseAvprWithStr(theAvprFile, "test.dt.stringOutFunc");
+    CHECK(dynFunc != nullptr);
+
+    int handle = 0;
+    int* handle_ptr = &handle;
+
+    char * out = nullptr;
+    char ** out_ptr = &out;
+
+    void *args[2];
+    args[0] = &handle_ptr;
+    args[1] = &out_ptr;
+    int rVal = 1;
+
+    int rc = dynFunction_call(dynFunc, fp, &rVal, args);
+    CHECK_EQUAL(0, rc);
+    STRCMP_EQUAL("result_out", out);
+
+    free(out);
+    dynFunction_destroy(dynFunc);
+}
+
+// Test 10, Test function with object with string as return value
+extern "C" {
+    struct tst_10 {
+        char * name;
+        int32_t id;
+    };
+}
+
+static int avpr_example10(__attribute__((unused))void *handle, struct tst_10 ** out) {
+    (*out)->name = strdup("my_new_char");
+    CHECK((*out)->name != nullptr);
+    (*out)->id = 132;
+    return 0;
+}
+
+TEST(DynAvprFunctionTests, Example10) {
+    auto fp = (void(*)()) avpr_example10;
+    dyn_function_type * dynFunc = dynFunction_parseAvprWithStr(theAvprFile, "test.dt.structStringOutFunc");
+    CHECK(dynFunc != nullptr);
+
+    int handle = 0;
+    int* handle_ptr = &handle;
+
+    tst_10 out {nullptr, 0};
+    struct tst_10 * out_ptr = &out;
+    struct tst_10 ** out_ptr_ptr = &out_ptr;
+
+    void *args[2];
+    args[0] = &handle_ptr;
+    args[1] = &out_ptr_ptr;
+    int rVal = 1;
+
+    int rc = dynFunction_call(dynFunc, fp, &rVal, args);
+    CHECK_EQUAL(0, rc);
+    CHECK_EQUAL(132, out.id);
+    STRCMP_EQUAL("my_new_char", out.name);
+
+    free(out.name);
+    dynFunction_destroy(dynFunc);
+}
diff --git a/libs/dfi/test/dyn_avpr_interface_tests.cpp b/libs/dfi/test/dyn_avpr_interface_tests.cpp
new file mode 100644
index 0000000..5d7d1e5
--- /dev/null
+++ b/libs/dfi/test/dyn_avpr_interface_tests.cpp
@@ -0,0 +1,174 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <CppUTest/TestHarness.h>
+#include "CppUTest/CommandLineTestRunner.h"                                                                                                                                                                        
+
+extern "C" {
+    #include <stdio.h>
+    #include <stdint.h>
+    #include <stdlib.h>
+    #include <string.h>
+    #include <ctype.h>
+    #include <stdarg.h>
+
+    #include "dyn_common.h"
+    #include "dyn_interface.h"
+
+    static void stdLog(void*, int level, const char *file, int line, const char *msg, ...) {
+        va_list ap;
+        const char *levels[5] = {"NIL", "ERROR", "WARNING", "INFO", "DEBUG"};
+        fprintf(stderr, "%s: FILE:%s, LINE:%i, MSG:",levels[level], file, line);
+        va_start(ap, msg);
+        vfprintf(stderr, msg, ap);
+        fprintf(stderr, "\n");
+        va_end(ap);
+    }
+}
+
+const char* theInvalidAvprFile = "{ \
+                \"protocol\" : \"the_interface\", \
+                \"namespace\" : \"test.dt\", \
+                \"version\" : \"1.1.0\", \
+                \"types\" : [ { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Sint\", \
+                    \"size\" : 4, \
+                    \"signed\" : true \
+                  } ] ,\
+                \"messages\" : { \
+                    \"aFunc\" : {\
+                        \"request\" : [ ],\
+                        \"response\" : \"Sint\" \
+                    } \
+                } \
+            }";
+
+const char* theBigAvprFile = "{ \
+                \"protocol\" : \"the_interface\", \
+                \"namespace\" : \"test.dt\", \
+                \"version\" : \"1.1.0\", \
+                \"types\" : [ { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Sint\", \
+                    \"size\" : 4, \
+                    \"signed\" : true \
+                } , { \
+                    \"type\" : \"fixed\", \
+                    \"namespace\" : \"nested\", \
+                    \"name\" : \"Double\", \
+                    \"alias\": \"double\", \
+                    \"size\" : 8 \
+                  } ] ,\
+                \"messages\" : { \
+                    \"simpleFunc\" : {\
+                        \"index\" : 0, \
+                        \"request\" : [ {\
+                                \"name\" : \"arg1\", \
+                                \"type\" : \"Sint\" \
+                            } , { \
+                                \"name\" : \"arg2\", \
+                                \"type\" : \"Sint\" \
+                            } , { \
+                                \"name\" : \"arg3\", \
+                                \"type\" : \"Sint\", \
+                                \"ptr\" : true \
+                            } ],\
+                        \"response\" : \"Sint\" \
+                    }, \
+                    \"aFunc\" : {\
+                        \"index\" : 1, \
+                        \"request\" : [ {\
+                                \"name\" : \"m_arg\", \
+                                \"type\" : \"Sint\" \
+                            } ],\
+                        \"response\" : \"Sint\" \
+                    } \
+                } \
+            }";
+
+TEST_GROUP(DynAvprInterfaceTests) {
+    void setup() override {
+        int lvl = 1;
+        dynAvprInterface_logSetup(stdLog, nullptr, lvl);
+        dynAvprFunction_logSetup(stdLog, nullptr, lvl);
+        dynAvprType_logSetup(stdLog, nullptr, lvl);
+    }
+};
+
+static void checkInterfaceVersion(dyn_interface_type* dynIntf, const char* v) {
+    int status;
+
+    char *version = nullptr;
+    status = dynInterface_getVersionString(dynIntf, &version);
+    CHECK_EQUAL(0, status);
+    STRCMP_EQUAL(v, version);
+    version_pt msgVersion = nullptr, localMsgVersion = nullptr;
+    int cmpVersion = -1;
+    version_createVersionFromString(version, &localMsgVersion);
+    status = dynInterface_getVersion(dynIntf, &msgVersion);
+    CHECK_EQUAL(0, status);
+    version_compareTo(msgVersion, localMsgVersion, &cmpVersion);
+    CHECK_EQUAL(cmpVersion, 0);
+    version_destroy(localMsgVersion);
+}
+
+// Test 1, simply see if parsing works and if parsed correctly
+TEST(DynAvprInterfaceTests, Example1) {
+    dyn_interface_type *dynIntf = dynInterface_parseAvprWithStr(theBigAvprFile);
+    CHECK(dynIntf != nullptr);
+
+    // Check version
+    checkInterfaceVersion(dynIntf, "1.1.0");
+
+    // Check name
+    char *name = nullptr;
+    dynInterface_getName(dynIntf, &name);
+    CHECK(name != nullptr);
+    STRCMP_EQUAL("the_interface", name);
+
+    // Check annotation (namespace)
+    char *annVal = nullptr;
+    dynInterface_getAnnotationEntry(dynIntf, "namespace", &annVal);
+    CHECK(annVal != nullptr);
+    STRCMP_EQUAL("test.dt", annVal);
+
+    // Check nonexisting
+    char *nonExist = nullptr;
+    dynInterface_getHeaderEntry(dynIntf, "nonExisting", &nonExist);
+    CHECK(nonExist == nullptr);
+
+    // Get lists of methods
+    struct methods_head *list = nullptr;
+    int status = dynInterface_methods(dynIntf, &list);
+    CHECK(status == 0);
+    CHECK(list != nullptr);
+
+    int count = dynInterface_nrOfMethods(dynIntf);
+    CHECK_EQUAL(2, count);
+
+    dynInterface_destroy(dynIntf);
+}
+
+// Invalid tests 
+TEST(DynAvprInterfaceTests, InvalidExample) {
+    dyn_interface_type *dynIntf = dynInterface_parseAvprWithStr(theInvalidAvprFile);
+    CHECK(dynIntf == nullptr);
+}
+
diff --git a/libs/dfi/test/dyn_avpr_tests.cpp b/libs/dfi/test/dyn_avpr_tests.cpp
new file mode 100644
index 0000000..69ff3d9
--- /dev/null
+++ b/libs/dfi/test/dyn_avpr_tests.cpp
@@ -0,0 +1,514 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+#include "CppUTest/TestHarness.h"
+#include "CppUTest/CommandLineTestRunner.h"                                                                                                                                                                        
+
+extern "C" {
+    #include <stdarg.h>
+    
+    #include "dyn_common.h"
+    #include "dyn_type.h"
+
+	static void stdLogA(void*, int level, const char *file, int line, const char *msg, ...) {
+	    va_list ap;
+	    const char *levels[5] = {"NIL", "ERROR", "WARNING", "INFO", "DEBUG"};
+	    fprintf(stderr, "%s: FILE:%s, LINE:%i, MSG:",levels[level], file, line);
+	    va_start(ap, msg);
+	    vfprintf(stderr, msg, ap);
+	    fprintf(stderr, "\n");
+	    va_end(ap);
+	}
+
+    static void runTestA(const char *descriptorStr, const char *exName, int expectedType) {
+        dyn_type *type;
+        type = dynType_parseAvprWithStr(descriptorStr, exName);
+
+        if (type != nullptr) {
+            CHECK_EQUAL(expectedType, dynType_type(type));
+            dynType_destroy(type);
+        } else {
+            CHECK_EQUAL(1, 0);
+        }
+    }
+}
+
+const char* theTestCase = "{ \
+                \"protocol\" : \"types\", \
+                \"namespace\" : \"test.dt\", \
+                \"version\" : \"1.1.9\", \
+                \"CpfCInclude\" : \"time.h\", \
+                \"types\" : [ { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"uint\", \
+                    \"version\" : \"2.1.9\", \
+                    \"size\" : 4, \
+                    \"signed\" : true \
+                  }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"ulong\", \
+                    \"size\" : 8, \
+                    \"namespace\" : \"blah.test.dt\" \
+                  }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"double\", \
+                    \"alias\" : \"double\", \
+                    \"size\" : 8 \
+                  }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"B\", \
+                    \"fields\" : [ \
+                    { \
+                        \"name\" : \"aa\", \
+                        \"type\" : \"uint\" \
+                    },\
+                    { \
+                        \"name\" : \"bb\", \
+                        \"type\" : \"uint\" \
+                    }\
+                    ,\
+                    { \
+                        \"name\" : \"cc\", \
+                        \"type\" : \"double\" \
+                    }\
+                    ] \
+                  }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"long\", \
+                    \"size\" : 8, \
+                    \"namespace\" : \"other.dt\", \
+                    \"signed\" : true \
+                  }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"A\", \
+                    \"namespace\" : \"blah.test.dt\", \
+                    \"fields\" : [\
+                    { \
+                        \"name\" : \"x\", \
+                        \"type\" : \"test.dt.B\" \
+                    },\
+                    { \
+                        \"name\" : \"y\", \
+                        \"type\" : \"ulong\" \
+                    }\
+                    ] \
+                  }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"V\", \
+                    \"fields\" : [\
+                    {\
+                        \"name\" : \"elem\", \
+                        \"type\" : {\
+                            \"type\" : \"array\",\
+                            \"items\" : \"uint\",\
+                            \"static\" : 3\
+                        }\
+                    }\
+                    ]\
+                  }, { \
+                    \"type\" : \"enum\", \
+                    \"name\" : \"EnumWithValue\", \
+                    \"EnumValues\" : [ \"A = 3\", \"B= 1234\" ],\
+                    \"symbols\" : [\"A\", \"B\"]\
+                  }, { \
+                    \"type\" : \"enum\", \
+                    \"name\" : \"EnumWithoutValue\", \
+                    \"symbols\" : [\"A\", \"B\"]\
+		  }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"Anne\", \
+                    \"alias\" : \"CoolType\", \
+                    \"MsgId\" : 1000, \
+                    \"Invalid\" : {}, \
+                    \"fields\" : [ {\
+                        \"name\" : \"data\", \
+                        \"type\" :\"test.dt.double\" \
+                    } ]\
+                  }, { \
+                    \"type\" : \"record\", \
+                    \"namespace\" : \"N\", \
+                    \"name\" : \"Node\", \
+                    \"fields\" : [ {\
+                        \"name\" : \"data\", \
+                        \"type\" :\"test.dt.double\" \
+                      }, {\
+                        \"name\" : \"ne_elem_left\", \
+                        \"type\" : \"Node\", \
+                        \"ptr\" : true \
+                      }, {\
+                        \"name\" : \"ne_elem_right\", \
+                        \"type\" : \"Node\", \
+                        \"ptr\" : true \
+                    } ]\
+                  } ] ,\
+                \"messages\" : {} \
+            }";
+
+const char* nestedArray = "{\
+                \"protocol\" : \"types\", \
+                \"namespace\" : \"test.dt\", \
+                \"version\" : \"1.0.0\", \
+                \"types\" : [ { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"uint\", \
+                    \"size\" : 4, \
+                    \"signed\" : true \
+                  }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"NA\", \
+                    \"fields\" : [\
+                    { \
+                        \"name\" : \"members\", \
+                        \"type\" : {\
+                            \"type\" : \"array\",\
+                            \"items\" : {\
+                                \"type\" : \"array\",\
+                                \"items\" : \"uint\",\
+                                \"static\" : 3\
+                            },\
+                            \"static\" : 3\
+                        }\
+                    } ] \
+                  }] , \
+                \"messages\" : {} \
+                           }";
+
+const char* referenceTestCase = "{\
+                \"protocol\" : \"types\", \
+                \"namespace\" : \"test.dt\", \
+                \"version\" : \"1.0.0\", \
+                \"types\" : [ { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"uint\", \
+                    \"size\" : 4, \
+                    \"signed\" : true \
+                  }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"X\", \
+                    \"fields\" : [\
+                    { \
+                        \"name\" : \"xx\", \
+                        \"type\" : \"uint\" \
+                    }, { \
+                        \"name\" : \"level_a\", \
+                        \"type\" : \"X\", \
+                        \"ptr\" : true \
+                    }, { \
+                        \"name\" : \"level_b\", \
+                        \"type\" : \"X\", \
+                        \"ptr\" : true \
+                    } ] \
+                  }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"R\", \
+                    \"fields\" : [\
+                    { \
+                        \"name\" : \"data\", \
+                        \"type\" : \"X\", \
+                        \"ptr\" : true \
+                    } ] \
+                  }] , \
+                \"messages\" : {} \
+           }";
+
+
+/*********************************************************************************
+ * Type building tests
+ */
+
+TEST_GROUP(DynAvprTypeTests) {
+	void setup() override {
+	    dynAvprType_logSetup(stdLogA, nullptr, 3);
+	}
+};
+
+TEST(DynAvprTypeTests, SimpleTest) {
+    runTestA(theTestCase, "test.dt.uint", DYN_TYPE_SIMPLE);
+}
+
+TEST(DynAvprTypeTests, ComplexTest) {
+    runTestA(theTestCase, "blah.test.dt.A", DYN_TYPE_COMPLEX);
+}
+
+TEST(DynAvprTypeTests, EnumTest2) {
+    runTestA(theTestCase, "test.dt.EnumWithValue", DYN_TYPE_SIMPLE);
+}
+
+TEST(DynAvprTypeTests, EnumTest) {
+    runTestA(theTestCase, "test.dt.EnumWithoutValue", DYN_TYPE_SIMPLE);
+}
+
+TEST(DynAvprTypeTests, ArrayTest) {
+    runTestA(theTestCase, "test.dt.V", DYN_TYPE_COMPLEX);
+}
+
+TEST(DynAvprTypeTests, NestedArrayTest) {
+    runTestA(nestedArray, "test.dt.NA", DYN_TYPE_COMPLEX);
+}
+
+TEST(DynAvprTypeTests, ComplexComplexTest) {
+    runTestA(theTestCase, "test.dt.B", DYN_TYPE_COMPLEX);
+}
+
+TEST(DynAvprTypeTests, ReferenceTest) {
+    runTestA(referenceTestCase, "test.dt.R", DYN_TYPE_COMPLEX);
+}
+
+/*********************************************************************************
+ * Assignment tests + version testing
+ */
+
+void test_version(dyn_type* type, const std::string& version_string) {
+    struct meta_entry *entry = nullptr;
+    struct meta_properties_head *entries = nullptr;
+    CHECK_EQUAL(0, dynType_metaEntries(type, &entries));
+    CHECK_FALSE(TAILQ_EMPTY(entries));
+
+    const std::string entry_value {"version"};
+    bool compared = false;
+    TAILQ_FOREACH(entry, entries, entries) {
+        if (entry_value == entry->name) {
+            STRCMP_EQUAL(version_string.c_str(), entry->value);
+            compared = true;
+        }
+    }
+    CHECK_TRUE_TEXT(compared, "Expect a comparison, otherwise no version meta info is available");
+}
+
+TEST_GROUP(DynAvprAssignTests) {
+	void setup() override {
+	    dynAvprType_logSetup(stdLogA, nullptr, 1);
+	}
+};
+
+TEST(DynAvprAssignTests, AssignSimpleTest) {
+    // Build type
+    dyn_type* type = dynType_parseAvprWithStr(theTestCase, "test.dt.uint");
+    CHECK(type != nullptr);
+
+    // set value
+    uint32_t simple = 0;
+    uint32_t nv = 42;
+    dynType_simple_setValue(type, &simple, &nv);
+
+    CHECK_EQUAL(42, simple);
+    test_version(type, "2.1.9");
+    dynType_destroy(type);
+}
+
+TEST(DynAvprAssignTests, AssignComplexTest) {
+    // Build type
+    struct exA {
+        struct {
+            uint32_t aa;
+            uint32_t bb;
+            double cc;
+        } x;
+        uint64_t y;
+    };
+
+
+    dyn_type *type = dynType_parseAvprWithStr(theTestCase, "blah.test.dt.A");
+    CHECK(type != nullptr);
+
+    // set example values
+    uint32_t a_x_aa = 52;
+    uint32_t a_x_bb = 42;
+    double a_x_cc = 31.13;
+    uint64_t a_y = 1001001;
+
+    // Simple element in complex
+    exA inst {{0, 0, 0.0}, 0};
+    dynType_complex_setValueAt(type, 1, &inst, &a_y);
+    CHECK_EQUAL(1001001, inst.y);
+
+    // Complex element in complex type, first acquire subtype, then check similar to simple type
+    void *loc = nullptr;
+    dyn_type *subType = nullptr;
+    dynType_complex_valLocAt(type, 0, static_cast<void*>(&inst), &loc);
+    dynType_complex_dynTypeAt(type, 0, &subType);
+
+    dynType_complex_setValueAt(subType, 0, &inst.x, &a_x_aa);
+    CHECK_EQUAL(52, inst.x.aa);
+
+    dynType_complex_setValueAt(subType, 1, &inst.x, &a_x_bb);
+    CHECK_EQUAL(42, inst.x.bb);
+    dynType_complex_setValueAt(subType, 2, &inst.x, &a_x_cc);
+    CHECK_EQUAL(31.13, inst.x.cc);
+
+    test_version(type, "1.1.9");
+    dynType_destroy(type);
+}
+
+TEST(DynAvprAssignTests, AssignPtrTest) {
+    // Build type
+
+    struct exNode {
+        double data;
+        exNode *ne_elem_left;
+        exNode *ne_elem_right;
+    };
+
+    dyn_type* type = dynType_parseAvprWithStr(theTestCase, "N.Node");
+    CHECK(type != nullptr);
+
+    // right tree
+    exNode rightrightright {2.0, nullptr, nullptr};
+    exNode rightleft {0.5, nullptr, nullptr};
+    exNode rightright {1.5, nullptr, &rightrightright};
+    exNode right {1.0, &rightleft, &rightright};
+
+    // left tree
+    exNode leftleft {-1.5, nullptr, nullptr};
+    exNode leftright {-0.5, nullptr, nullptr};
+    exNode left {-1.0, &leftleft, &leftright};
+
+    // Base
+    exNode base {0.0, &left, &right};
+
+    double nv = 101.101;
+    dynType_complex_setValueAt(type, 0, &base, &nv);
+    CHECK_EQUAL(101.101, base.data);
+
+    test_version(type, "1.1.9");
+    dynType_destroy(type);
+}
+
+TEST(DynAvprAssignTests, AssignEnumTest) {
+    // Build type
+    dyn_type* type = dynType_parseAvprWithStr(theTestCase, "test.dt.EnumWithValue");
+    dyn_type* type_2 = dynType_parseAvprWithStr(theTestCase, "test.dt.EnumWithoutValue");
+    CHECK(type != nullptr);
+    CHECK(type_2 != nullptr);
+
+    // Print type
+    dynType_print(type, stdout);
+    dynType_print(type_2, stdout);
+
+    // set value
+    enum exEnumV {A=3, B=1234};
+    enum exEnumV mEnum = B;
+    enum exEnumV nv = A;
+
+    dynType_simple_setValue(type, &mEnum, &nv);
+
+    CHECK_EQUAL(A, mEnum);
+    test_version(type, "1.1.9");
+    dynType_destroy(type);
+    dynType_destroy(type_2);
+}
+
+TEST(DynAvprAssignTests, AssignArrayTest) {
+    // Build type
+    struct exV_sequence {
+        uint32_t cap;
+        uint32_t len;
+        uint32_t **buf;
+    };
+
+    struct exV {
+        struct exV_sequence elem;
+    };
+
+    exV inst {exV_sequence{0,0, nullptr}};
+    exV_sequence *s = &inst.elem;
+
+    dyn_type* type = dynType_parseAvprWithStr(theTestCase, "test.dt.V");
+    CHECK(type != nullptr);
+
+    // set value
+    void *loc = nullptr;
+    dyn_type *subType = nullptr;
+    dynType_complex_valLocAt(type, 0, static_cast<void*>(&inst), &loc);
+    dynType_complex_dynTypeAt(type, 0, &subType);
+    int res = dynType_alloc(subType, reinterpret_cast<void**>(&s));
+    CHECK_EQUAL(0, res);
+    CHECK(s != nullptr);
+
+    dynType_free(type, s);
+    test_version(type, "1.1.9");
+    dynType_destroy(type);
+}
+
+TEST(DynAvprAssignTests, AnnotationTest) {
+    dyn_type* type = dynType_parseAvprWithStr(theTestCase, "test.dt.Anne");
+    CHECK(type != nullptr);
+
+    // get value for meta entry
+    struct meta_entry *entry = nullptr;
+    struct meta_properties_head *entries = nullptr;
+    CHECK_EQUAL(0, dynType_metaEntries(type, &entries));
+    CHECK_FALSE(TAILQ_EMPTY(entries));
+
+    const std::string msg_id_entry {"MsgId"};
+    bool compared = false;
+
+    TAILQ_FOREACH(entry, entries, entries) {
+        printf("Got an entry: %s\n", entry->name);
+        if (msg_id_entry == entry->name) {
+            STRCMP_EQUAL("1000", entry->value);
+            compared = true;
+        }
+    }
+    CHECK_TRUE_TEXT(compared, "Expect a comparison, otherwise no msg id entry available");
+
+    dynType_destroy(type);
+}
+
+/*********************************************************************************
+ * Invalid tests
+ */
+TEST_GROUP(DynAvprInvalidTests) {
+	void setup() override {
+	    dynAvprType_logSetup(stdLogA, nullptr, 1);
+	}
+};
+
+TEST(DynAvprInvalidTests, InvalidJson) {
+    dyn_type* type = dynType_parseAvprWithStr("{", "test.invalid.type"); // Json error
+    CHECK(type == nullptr);
+}
+
+TEST(DynAvprInvalidTests, InvalidJsonObject) {
+    dyn_type* type = dynType_parseAvprWithStr("[]", "test.invalid.type"); // Root should be object not list
+    CHECK(type == nullptr);
+    type = dynType_parseAvprWithStr("{}", "test.invalid.type"); // Root should have a namespace
+    CHECK(type == nullptr);
+    type = dynType_parseAvprWithStr(R"({"namespace":"nested"})", "test.invalid.type"); // Root should have types array
+    CHECK(type == nullptr);
+    type = dynType_parseAvprWithStr(
+            R"({"namespace":"nested", "types" : [] })"
+            , "test.invalid.type"); // types is empty, so not found
+    CHECK(type == nullptr);
+    type = dynType_parseAvprWithStr(
+            "{\"namespace\":\"nested\", \"types\" : [\
+            { \"type\" : \"record\", \"name\" : \"IncompleteStruct\", \"fields\" : [\
+            { \"name\" : \"Field1\", \"type\" : \"NonExisting\" } ] } \
+            ] }"
+            , "nested.IncompleteStruct"); // struct misses definition
+    CHECK(type == nullptr);
+    type = dynType_parseAvprWithStr(
+            "{\"namespace\":\"nested\", \"types\" : [\
+            { \"type\" : \"record\", \"name\" : \"IncompleteStruct\", \"fields\" : [\
+            { \"name\" : \"Field1\" } ] } \
+            ] }"
+            , "nested.IncompleteStruct"); // struct entry misses type
+    CHECK(type == nullptr);
+    // None of the above testcases should crash the parser
+}
+
diff --git a/libs/dfi/test/dyn_function_tests.cpp b/libs/dfi/test/dyn_function_tests.cpp
index 58ad662..b8996e2 100644
--- a/libs/dfi/test/dyn_function_tests.cpp
+++ b/libs/dfi/test/dyn_function_tests.cpp
@@ -141,7 +141,7 @@ extern "C" {
 
     static int testExample3(void *ptr, double a, double *out) {
         double *b = (double *)ptr;
-        CHECK_EQUAL(2.0, *b)
+        CHECK_EQUAL(2.0, *b);
         CHECK_EQUAL(a, 2.0);
         *out = *b * a;
         return 0;
@@ -272,3 +272,4 @@ TEST(DynFunctionTests, InvalidDynFuncTest) {
     test_invalidDynFunc();
     test_invalidDynFuncType();
 }
+
diff --git a/libs/dfi/test/dyn_interface_tests.cpp b/libs/dfi/test/dyn_interface_tests.cpp
index 5220d51..7c63d37 100644
--- a/libs/dfi/test/dyn_interface_tests.cpp
+++ b/libs/dfi/test/dyn_interface_tests.cpp
@@ -205,3 +205,4 @@ TEST(DynInterfaceTests, test2) {
 TEST(DynInterfaceTests, testInvalid) {
     testInvalid();
 }
+
diff --git a/libs/dfi/test/dyn_message_tests.cpp b/libs/dfi/test/dyn_message_tests.cpp
index 35c7f1d..ed7d441 100644
--- a/libs/dfi/test/dyn_message_tests.cpp
+++ b/libs/dfi/test/dyn_message_tests.cpp
@@ -251,3 +251,4 @@ TEST(DynMessageTests, msg_test4) {
 TEST(DynMessageTests, msg_invalid) {
 	msg_invalid();
 }
+
diff --git a/libs/dfi/test/dyn_type_tests.cpp b/libs/dfi/test/dyn_type_tests.cpp
index 52f9537..eb1d7f1 100644
--- a/libs/dfi/test/dyn_type_tests.cpp
+++ b/libs/dfi/test/dyn_type_tests.cpp
@@ -88,6 +88,7 @@ TEST_GROUP(DynTypeTests) {
 #define EX14 "{DD{FF{JJ}{II*{ss}}}}"  //unnamed fields
 #define EX15 "Tsample={jDD time val1 val2};Tresult={jDlsample; time result sample};Lresult;"
 #define EX16 "Tpoi={BDD id lat lon};Lpoi;"
+#define EX17 "{#v1=0;#v2=1;E#v1=9;#v2=10;E enum1 enum2}"
 
 #define CREATE_EXAMPLES_TEST(DESC) \
     TEST(DynTypeTests, ParseTestExample ## DESC) { \
@@ -110,6 +111,7 @@ CREATE_EXAMPLES_TEST(EX13)
 CREATE_EXAMPLES_TEST(EX14)
 CREATE_EXAMPLES_TEST(EX15)
 CREATE_EXAMPLES_TEST(EX16)
+CREATE_EXAMPLES_TEST(EX17)
 
 TEST(DynTypeTests, ParseRandomGarbageTest) {
     /*
@@ -295,3 +297,12 @@ TEST(DynTypeTests, SequenceWithPointerTest) {
     dynType_destroy(type);
 }
 
+TEST(DynTypeTests, EnumTest) {
+    dyn_type *type = NULL;
+    int rc = 0;
+    rc = dynType_parseWithStr("{#v1=0;#v2=1;E#v1=9;#v2=10;E enum1 enum2}", NULL, NULL, &type);
+    CHECK_EQUAL(0, rc);
+
+    dynType_print(type, stdout);
+    dynType_destroy(type);
+}
diff --git a/libs/dfi/test/json_rpc_avpr_tests.cpp b/libs/dfi/test/json_rpc_avpr_tests.cpp
new file mode 100644
index 0000000..7c52179
--- /dev/null
+++ b/libs/dfi/test/json_rpc_avpr_tests.cpp
@@ -0,0 +1,384 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <CppUTest/TestHarness.h>
+#include "CppUTest/CommandLineTestRunner.h"                                                                                                                                                                        
+
+extern "C" {
+    #include <stdio.h>
+    #include <stdint.h>
+    #include <stdlib.h>
+    #include <string.h>
+    #include <ctype.h>
+    #include <stdarg.h>
+    #include <assert.h>
+    #include <float.h>
+
+    #include <ffi.h>
+
+    #include "dyn_common.h"
+    #include "dyn_type.h"
+    #include "dyn_interface.h"
+
+    #include "json_serializer.h"
+    #include "json_rpc.h"
+
+    static void stdLog(void*, int level, const char *file, int line, const char *msg, ...) {
+        va_list ap;
+        const char *levels[5] = {"NIL", "ERROR", "WARNING", "INFO", "DEBUG"};
+        fprintf(stderr, "%s: FILE:%s, LINE:%i, MSG:",levels[level], file, line);
+        va_start(ap, msg);
+        vfprintf(stderr, msg, ap);
+        fprintf(stderr, "\n");
+        va_end(ap);
+    }
+}
+
+extern "C" {
+    const char* sourceAvprFile = "{ \
+                \"protocol\" : \"calculator\", \
+                \"namespace\" : \"test.rpc\", \
+                \"version\" : \"1.0.0\", \
+                \"types\" : [ { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Double\", \
+                    \"alias\": \"double\", \
+                    \"size\" : 8 \
+                  }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"String\", \
+                    \"alias\": \"string\", \
+                    \"size\" : 8 \
+                  }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"TwoDoubles\", \
+                    \"fields\" : [ { \
+                          \"name\" : \"a\", \
+                          \"type\" : \"Double\" \
+                        } , { \
+                          \"name\" : \"b\", \
+                          \"type\" : \"Double\" \
+                        } ] \
+                  }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"StatsResult\", \
+                    \"fields\" : [ { \
+                          \"name\" : \"average\", \
+                          \"type\" : \"Double\" \
+                        } , { \
+                          \"name\" : \"min\", \
+                          \"type\" : \"Double\" \
+                        } , { \
+                          \"name\" : \"max\", \
+                          \"type\" : \"Double\" \
+                        } , { \
+                          \"name\" : \"input\", \
+                          \"type\" : { \
+                            \"type\" : \"array\",\
+                            \"items\" : \"Double\"\
+                          } \
+                        } ] \
+                  } ] ,\
+                \"messages\" : { \
+                    \"add\" : {\
+                        \"index\" : 0, \
+                        \"request\" : [ {\
+                                \"name\" : \"arg1\", \
+                                \"type\" : \"Double\" \
+                            } , { \
+                                \"name\" : \"arg2\", \
+                                \"type\" : \"Double\" \
+                            } ],\
+                        \"response\" : \"Double\" \
+                    }, \
+                    \"sub\" : {\
+                        \"index\" : 1, \
+                        \"request\" : [ {\
+                                \"name\" : \"arg1\", \
+                                \"type\" : \"Double\" \
+                            } , { \
+                                \"name\" : \"arg2\", \
+                                \"type\" : \"Double\" \
+                            } ],\
+                        \"response\" : \"Double\" \
+                    }, \
+                    \"sqrt\" : {\
+                        \"index\" : 2, \
+                        \"request\" : [ {\
+                                \"name\" : \"arg1\", \
+                                \"type\" : \"Double\" \
+                            } ],\
+                        \"response\" : \"Double\" \
+                    }, \
+                    \"stats\" : {\
+                        \"index\" : 3, \
+                        \"request\" : [ {\
+                                \"name\" : \"arg1\", \
+                                \"type\" : { \
+                                  \"type\" : \"array\",\
+                                  \"items\" : \"Double\"\
+                                } \
+                            } ],\
+                        \"response\" : \"StatsResult\" \
+                    }, \
+                    \"retArray\" : {\
+                        \"index\" : 0, \
+                        \"request\" : [ ],\
+                        \"response\" : { \
+                                  \"type\" : \"array\",\
+                                  \"items\" : \"TwoDoubles\"\
+                                } \
+                    }, \
+                    \"getName\" : {\
+                        \"index\" : 0, \
+                        \"request\" : [ ],\
+                        \"response\" : \"String\" \
+                    } \
+                } \
+            }";
+}
+
+TEST_GROUP(JsonAvprRpcTests) {
+    void setup() override {
+        int lvl = 1;
+        dynCommon_logSetup(stdLog, nullptr, lvl);
+        dynType_logSetup(stdLog, nullptr,lvl);
+        dynFunction_logSetup(stdLog, nullptr,lvl);
+        dynInterface_logSetup(stdLog, nullptr,lvl);
+        jsonSerializer_logSetup(stdLog, nullptr, lvl);
+        jsonRpc_logSetup(stdLog, nullptr, lvl);
+    }
+};
+
+TEST(JsonAvprRpcTests, prep) {
+    dyn_function_type * func = dynFunction_parseAvprWithStr(sourceAvprFile, "test.rpc.add");
+    CHECK(func != nullptr);
+    int nof_args = dynFunction_nrOfArguments(func);
+    CHECK_EQUAL(4, nof_args);
+
+    // Msg
+    char *result = nullptr;
+    void *handle = nullptr;
+
+    double arg1 = 1.0;
+    double arg2 = 2.0;
+
+    void *args[4];
+    args[0] = &handle;
+    args[1] = &arg1;
+    args[2] = &arg2;
+
+    int rc = jsonRpc_prepareInvokeRequest(func, "add", args, &result);
+    CHECK_EQUAL(0, rc);
+
+    STRCMP_CONTAINS("\"add\"", result);
+    STRCMP_CONTAINS("1.0", result);
+    STRCMP_CONTAINS("2.0", result);
+
+    // Reply
+    const char *reply = "{\"r\": 2.2}";
+    double calc_result = -1.0;
+    double *out = &calc_result;
+    //double **out_ptr = &out;
+    args[3] = &out;
+
+    rc = jsonRpc_handleReply(func, reply, args);
+    CHECK_EQUAL(0, rc);
+    DOUBLES_EQUAL(2.2, calc_result, 0.001);
+
+    free(result);
+    dynFunction_destroy(func);
+}
+
+// Test handle out
+extern "C" {
+    struct tst_seq {
+        uint32_t cap;
+        uint32_t len;
+        double *buf;
+    };
+
+    struct tst_StatsResult {
+        double average;
+        double min;
+        double max;
+        tst_seq input;
+    };
+}
+
+TEST(JsonAvprRpcTests, handle_out) {
+    dyn_interface_type * intf = dynInterface_parseAvprWithStr(sourceAvprFile);
+    CHECK(intf != nullptr);
+
+    methods_head *head;
+    dynInterface_methods(intf, &head);
+
+    dyn_function_type *func = nullptr;
+    method_entry *entry = nullptr;
+    TAILQ_FOREACH(entry, head, entries) {
+        if (strcmp(entry->name, "stats") == 0) {
+            func = entry->dynFunc;
+            break;
+        }
+    }
+    CHECK(func != nullptr);
+    int nof_args = dynFunction_nrOfArguments(func);
+    CHECK_EQUAL(3, nof_args);
+
+    const char *reply = R"({"r":{"input":[1.0,2.0],"max":2.0,"average":1.5,"min":1.0}})";
+
+    void *args[3];
+    args[0] = nullptr;
+    args[1] = nullptr;
+    args[2] = nullptr;
+
+    struct tst_StatsResult *result = nullptr;
+    void *out = &result;
+    args[2] = &out;
+
+    int rc = jsonRpc_handleReply(func, reply, args);
+    CHECK_EQUAL(0, rc);
+    CHECK(result != nullptr);
+    CHECK_EQUAL(1.5, result->average);
+
+    free(result->input.buf);
+    free(result);
+    dynInterface_destroy(intf);
+}
+
+
+// Test pre allocated
+
+extern "C" {
+    struct tst_serv {
+        void *handle;
+        int (*add)(void *, double, double, double *);
+        int (*sub)(void *, double, double, double *);
+        int (*sqrt)(void *, double, double *);
+        int (*stats)(void *, tst_seq, tst_StatsResult **);
+    };
+
+    int xadd(void*, double a, double b, double *result) {
+        *result = a + b;
+        return 0;
+    }
+}
+
+TEST(JsonAvprRpcTests, preallocated) {
+    dyn_interface_type * intf = dynInterface_parseAvprWithStr(sourceAvprFile);
+    CHECK(intf != nullptr);
+
+    char *result = nullptr;
+    tst_serv serv {nullptr, xadd, nullptr, nullptr, nullptr};
+
+    int rc = jsonRpc_call(intf, &serv, R"({"m": "add", "a": [1.0,2.0]})", &result);
+    CHECK_EQUAL(0, rc);
+    CHECK(result != nullptr);
+    STRCMP_CONTAINS("3.0", result);
+
+    free(result);
+    dynInterface_destroy(intf);
+}
+
+
+// Test output
+extern "C" {
+    int xstats(void*, struct tst_seq input, struct tst_StatsResult **out) {
+        assert(out != nullptr);
+        assert(*out == nullptr);
+        double total = 0.0;
+        unsigned int count = 0;
+        auto max = DBL_MIN;
+        auto min = DBL_MAX;
+
+        unsigned int i;
+        for (i = 0; i<input.len; i += 1) {
+            total += input.buf[i];
+            count += 1;
+            if (input.buf[i] > max) {
+                max = input.buf[i];
+            }
+            if (input.buf[i] < min) {
+                min = input.buf[i];
+            }
+        }
+
+        auto result = static_cast<tst_StatsResult *>(calloc(1, sizeof(tst_StatsResult)));
+        CHECK(result != nullptr);
+        if (count>0) {
+            result->average = total / count;
+        }
+        result->min = min;
+        result->max = max;
+        auto buf = static_cast<double *>(calloc(input.len, sizeof(double)));
+        CHECK(buf != nullptr);
+        memcpy(buf, input.buf, input.len * sizeof(double));
+        result->input.len = input.len;
+        result->input.cap = input.len;
+        result->input.buf = buf;
+
+        *out = result;
+        return 0;
+    }
+}
+
+TEST(JsonAvprRpcTests, output) {
+    dyn_interface_type * intf = dynInterface_parseAvprWithStr(sourceAvprFile);
+    CHECK(intf != nullptr);
+
+    char *result = nullptr;
+    tst_serv serv {nullptr, nullptr, nullptr, nullptr, xstats};
+
+    int rc = jsonRpc_call(intf, &serv, R"({"m":"stats", "a": [[1.0, 2.0]]})", &result);
+    CHECK_EQUAL(0, rc);
+    STRCMP_CONTAINS("1.5", result); //avg
+
+    free(result);
+    dynInterface_destroy(intf);
+}
+
+// Test char array as output
+extern "C" {
+    struct tst_service_ex_output_char {
+        void *handle;
+        int (*getName_x)(void *, char ** result);
+    };
+
+    int getName_ex(void*, char** result) {
+        *result = strdup("allocatedInFunction");
+        return 0;
+    }
+}
+
+TEST(JsonAvprRpcTests, output_char) {
+    dyn_interface_type * intf = dynInterface_parseAvprWithStr(sourceAvprFile);
+    CHECK(intf != nullptr);
+
+    char *result = nullptr;
+    tst_service_ex_output_char serv {nullptr, getName_ex};
+
+    int rc = jsonRpc_call(intf, &serv, R"({"m" : "getName", "a": []})", &result);
+    CHECK_EQUAL(0, rc);
+
+    STRCMP_CONTAINS("allocatedInFunction", result);
+
+    free(result);
+    dynInterface_destroy(intf);
+}
+
diff --git a/libs/dfi/test/json_rpc_tests.cpp b/libs/dfi/test/json_rpc_tests.cpp
index bff582e..2c66f44 100644
--- a/libs/dfi/test/json_rpc_tests.cpp
+++ b/libs/dfi/test/json_rpc_tests.cpp
@@ -47,13 +47,13 @@ static void stdLog(void*, int level, const char *file, int line, const char *msg
 
 
     void prepareTest(void) {
-        dyn_function_type *dynFunc = NULL;
-        int rc = dynFunction_parseWithStr("add(#am=handle;PDD#am=pre;*D)N", NULL, &dynFunc);
+        dyn_function_type *dynFunc = nullptr;
+        int rc = dynFunction_parseWithStr("add(#am=handle;PDD#am=pre;*D)N", nullptr, &dynFunc);
         CHECK_EQUAL(0, rc);
 
-        char *result = NULL;
+        char *result = nullptr;
 
-        void *handle = NULL;
+        void *handle = nullptr;
         double arg1 = 1.0;
         double arg2 = 2.0;
 
@@ -76,8 +76,8 @@ static void stdLog(void*, int level, const char *file, int line, const char *msg
     }
 
     void handleTestPre(void) {
-        dyn_function_type *dynFunc = NULL;
-        int rc = dynFunction_parseWithStr("add(#am=handle;PDD#am=pre;*D)N", NULL, &dynFunc);
+        dyn_function_type *dynFunc = nullptr;
+        int rc = dynFunction_parseWithStr("add(#am=handle;PDD#am=pre;*D)N", nullptr, &dynFunc);
         CHECK_EQUAL(0, rc);
 
         const char *reply = "{\"r\":2.2}";
@@ -119,12 +119,12 @@ static void stdLog(void*, int level, const char *file, int line, const char *msg
 
 
     int stats(void*, struct tst_seq input, struct tst_StatsResult **out) {
-        assert(out != NULL);
-        assert(*out == NULL);
+        assert(out != nullptr);
+        assert(*out == nullptr);
         double total = 0.0;
         unsigned int count = 0;
-        double max = DBL_MIN;
-        double min = DBL_MAX;
+        auto max = DBL_MIN;
+        auto min = DBL_MAX;
 
         unsigned int i;
         for (i = 0; i<input.len; i += 1) {
@@ -138,13 +138,13 @@ static void stdLog(void*, int level, const char *file, int line, const char *msg
             }
         }
 
-        struct tst_StatsResult *result = (struct tst_StatsResult *) calloc(1, sizeof(*result));
-        if(count>0){
-		result->average = total / count;
+        auto result = static_cast<tst_StatsResult *>(calloc(1, sizeof(tst_StatsResult)));
+        if(count>0) {
+		    result->average = total / count;
         }
         result->min = min;
         result->max = max;
-        double *buf = (double *)calloc(input.len, sizeof(double));
+        auto buf = static_cast<double *>(calloc(input.len, sizeof(double)));
         memcpy(buf, input.buf, input.len * sizeof(double));
         result->input.len = input.len;
         result->input.cap = input.len;
@@ -179,21 +179,17 @@ static void stdLog(void*, int level, const char *file, int line, const char *msg
     };
 
     void callTestPreAllocated(void) {
-        dyn_interface_type *intf = NULL;
+        dyn_interface_type *intf = nullptr;
         FILE *desc = fopen("descriptors/example1.descriptor", "r");
-        CHECK(desc != NULL);
+        CHECK(desc != nullptr);
         int rc = dynInterface_parse(desc, &intf);
         CHECK_EQUAL(0, rc);
         fclose(desc);
 
-        char *result = NULL;
+        char *result = nullptr;
+        tst_serv serv {nullptr, add, nullptr, nullptr, nullptr};
 
-        struct tst_serv serv;
-        serv.handle = NULL;
-        serv.add = add;
-
-
-        rc = jsonRpc_call(intf, &serv, "{\"m\":\"add(DD)D\", \"a\": [1.0,2.0]}", &result);
+        rc = jsonRpc_call(intf, &serv, R"({"m":"add(DD)D", "a": [1.0,2.0]})", &result);
         CHECK_EQUAL(0, rc);
         STRCMP_CONTAINS("3.0", result);
 
@@ -202,20 +198,17 @@ static void stdLog(void*, int level, const char *file, int line, const char *msg
     }
 
     void callTestOutput(void) {
-        dyn_interface_type *intf = NULL;
+        dyn_interface_type *intf = nullptr;
         FILE *desc = fopen("descriptors/example1.descriptor", "r");
-        CHECK(desc != NULL);
+        CHECK(desc != nullptr);
         int rc = dynInterface_parse(desc, &intf);
         CHECK_EQUAL(0, rc);
         fclose(desc);
 
-        char *result = NULL;
-
-        struct tst_serv serv;
-        serv.handle = NULL;
-        serv.stats = stats;
+        char *result = nullptr;
+        tst_serv serv {nullptr, nullptr, nullptr, nullptr, stats};
 
-        rc = jsonRpc_call(intf, &serv, "{\"m\":\"stats([D)LStatsResult;\", \"a\": [[1.0,2.0]]}", &result);
+        rc = jsonRpc_call(intf, &serv, R"({"m":"stats([D)LStatsResult;", "a": [[1.0,2.0]]})", &result);
         CHECK_EQUAL(0, rc);
         STRCMP_CONTAINS("1.5", result); //avg
 
@@ -224,33 +217,33 @@ static void stdLog(void*, int level, const char *file, int line, const char *msg
     }
 
     void handleTestOut(void) {
-        dyn_interface_type *intf = NULL;
+        dyn_interface_type *intf = nullptr;
         FILE *desc = fopen("descriptors/example1.descriptor", "r");
-        CHECK(desc != NULL);
+        CHECK(desc != nullptr);
         int rc = dynInterface_parse(desc, &intf);
         CHECK_EQUAL(0, rc);
         fclose(desc);
 
         struct methods_head *head;
         dynInterface_methods(intf, &head);
-        dyn_function_type *func = NULL;
-        struct method_entry *entry = NULL;
+        dyn_function_type *func = nullptr;
+        struct method_entry *entry = nullptr;
         TAILQ_FOREACH(entry, head, entries) {
             if (strcmp(entry->name, "stats") == 0) {
                 func = entry->dynFunc;
                 break;
             }
         }
-        CHECK(func != NULL);
+        CHECK(func != nullptr);
 
-        const char *reply = "{\"r\":{\"input\":[1.0,2.0],\"max\":2.0,\"average\":1.5,\"min\":1.0}}";
+        const char *reply = R"({"r":{"input":[1.0,2.0],"max":2.0,"average":1.5,"min":1.0}})";
 
         void *args[3];
-        args[0] = NULL;
-        args[1] = NULL;
-        args[2] = NULL;
+        args[0] = nullptr;
+        args[1] = nullptr;
+        args[2] = nullptr;
 
-        struct tst_StatsResult *result = NULL;
+        struct tst_StatsResult *result = nullptr;
         void *out = &result;
         args[2] = &out;
 
@@ -263,36 +256,36 @@ static void stdLog(void*, int level, const char *file, int line, const char *msg
         dynInterface_destroy(intf);
     }
 
-    static void handleTestOutputSequence(void) {
-        dyn_interface_type *intf = NULL;
+    static void handleTestOutputSequence() {
+        dyn_interface_type *intf = nullptr;
         FILE *desc = fopen("descriptors/example2.descriptor", "r");
-        CHECK(desc != NULL);
+        CHECK(desc != nullptr);
         int rc = dynInterface_parse(desc, &intf);
         CHECK_EQUAL(0, rc);
         fclose(desc);
 
         struct methods_head *head;
         dynInterface_methods(intf, &head);
-        dyn_function_type *func = NULL;
-        struct method_entry *entry = NULL;
+        dyn_function_type *func = nullptr;
+        struct method_entry *entry = nullptr;
         TAILQ_FOREACH(entry, head, entries) {
             if (strcmp(entry->name, "example1") == 0) {
                 func = entry->dynFunc;
                 break;
             }
         }
-        CHECK(func != NULL);
+        CHECK(func != nullptr);
 
         //dyn_type *arg = dynFunction_argumentTypeForIndex(func, 1);
         //dynType_print(arg, stdout);
 
-        const char *reply = "{\"r\":[{\"a\":1.0,\"b\":1.5},{\"a\":2.0,\"b\":2.5}]}";
+        const char *reply = R"({"r":[{"a":1.0,"b":1.5},{"a":2.0,"b":2.5}]})";
 
         void *args[2];
-        args[0] = NULL;
-        args[1] = NULL;
+        args[0] = nullptr;
+        args[1] = nullptr;
 
-        struct item_seq *result = NULL;
+        struct item_seq *result = nullptr;
         void *out = &result;
         args[1] = &out;
 
@@ -318,20 +311,17 @@ static void stdLog(void*, int level, const char *file, int line, const char *msg
 
 
     void callTestOutChar(void) {
-        dyn_interface_type *intf = NULL;
+        dyn_interface_type *intf = nullptr;
         FILE *desc = fopen("descriptors/example4.descriptor", "r");
-        CHECK(desc != NULL);
+        CHECK(desc != nullptr);
         int rc = dynInterface_parse(desc, &intf);
         CHECK_EQUAL(0, rc);
         fclose(desc);
 
-        char *result = NULL;
+        char *result = nullptr;
+        tst_serv_example4 serv {nullptr, getName_example4};
 
-        struct tst_serv_example4 serv;
-        serv.handle = NULL;
-        serv.getName_example4 = getName_example4;
-
-        rc = jsonRpc_call(intf, &serv, "{\"m\":\"getName(V)t\", \"a\": []}", &result);
+        rc = jsonRpc_call(intf, &serv, R"({"m": "getName(V)t", "a": []})", &result);
         CHECK_EQUAL(0, rc);
 
         STRCMP_CONTAINS("allocatedInFunction", result);
@@ -342,17 +332,17 @@ static void stdLog(void*, int level, const char *file, int line, const char *msg
 
 
     void handleTestOutChar(void) {
-        dyn_interface_type *intf = NULL;
+        dyn_interface_type *intf = nullptr;
         FILE *desc = fopen("descriptors/example4.descriptor", "r");
-        CHECK(desc != NULL);
+        CHECK(desc != nullptr);
         int rc = dynInterface_parse(desc, &intf);
         CHECK_EQUAL(0, rc);
         fclose(desc);
 
         struct methods_head *head;
         dynInterface_methods(intf, &head);
-        dyn_function_type *func = NULL;
-        struct method_entry *entry = NULL;
+        dyn_function_type *func = nullptr;
+        struct method_entry *entry = nullptr;
         TAILQ_FOREACH(entry, head, entries) {
             if (strcmp(entry->name, "getName") == 0) {
                 func = entry->dynFunc;
@@ -360,18 +350,18 @@ static void stdLog(void*, int level, const char *file, int line, const char *msg
             }
         }
 
-        CHECK(func != NULL);
+        CHECK(func != nullptr);
 
-        const char *reply = "{\"r\": \"this is a test string\" }";
-        char *result = NULL;
+        const char *reply = R"({"r": "this is a test string"})";
+        char *result = nullptr;
         void *out = &result;
 
         void *args[2];
-        args[0] = NULL;
+        args[0] = nullptr;
         args[1] = &out;
 
-        if(func!=NULL){ // Check needed just to satisfy Coverity
-		rc = jsonRpc_handleReply(func, reply, args);
+        if (func != nullptr) { // Check needed just to satisfy Coverity
+		     jsonRpc_handleReply(func, reply, args);
         }
 
         STRCMP_EQUAL("this is a test string", result);
@@ -379,20 +369,17 @@ static void stdLog(void*, int level, const char *file, int line, const char *msg
         free(result);
         dynInterface_destroy(intf);
     }
-
-
 }
 
 TEST_GROUP(JsonRpcTests) {
-    void setup() {
+    void setup() override {
         int lvl = 1;
-        dynCommon_logSetup(stdLog, NULL, lvl);
-        dynType_logSetup(stdLog, NULL,lvl);
-        dynFunction_logSetup(stdLog, NULL,lvl);
-        dynInterface_logSetup(stdLog, NULL,lvl);
-        jsonSerializer_logSetup(stdLog, NULL, lvl);
-        jsonRpc_logSetup(stdLog, NULL, lvl);
-
+        dynCommon_logSetup(stdLog, nullptr, lvl);
+        dynType_logSetup(stdLog, nullptr,lvl);
+        dynFunction_logSetup(stdLog, nullptr,lvl);
+        dynInterface_logSetup(stdLog, nullptr,lvl);
+        jsonSerializer_logSetup(stdLog, nullptr, lvl);
+        jsonRpc_logSetup(stdLog, nullptr, lvl);
     }
 };
 
@@ -421,8 +408,6 @@ TEST(JsonRpcTests, handleOutSeq) {
     handleTestOutputSequence();
 }
 
-
-
 TEST(JsonRpcTests, callTestOutChar) {
     callTestOutChar();
 }
diff --git a/libs/dfi/test/json_serializer_tests.cpp b/libs/dfi/test/json_serializer_tests.cpp
index a52e4cc..32fa6b7 100644
--- a/libs/dfi/test/json_serializer_tests.cpp
+++ b/libs/dfi/test/json_serializer_tests.cpp
@@ -17,7 +17,7 @@
  *under the License.
  */
 #include <CppUTest/TestHarness.h>
-#include "CppUTest/CommandLineTestRunner.h"                                                                                                                                                                        
+#include "CppUTest/CommandLineTestRunner.h"
 
 extern "C" {
 #include <stdio.h>
@@ -28,6 +28,7 @@ extern "C" {
 
 #include <ffi.h>
 
+#include "dyn_type_common.h"
 #include "dyn_common.h"
 #include "dyn_type.h"
 #include "json_serializer.h"
@@ -46,6 +47,60 @@ static void stdLog(void*, int level, const char *file, int line, const char *msg
 /** struct type ******************************/
 const char *example1_descriptor = "{DJISF a b c d e}";
 
+static const char *avpr_example1_descriptor = "{\
+                \"protocol\" : \"types\", \
+                \"namespace\" : \"test.ns\", \
+                \"version\" : \"1.0.0\", \
+                \"types\" : [ { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Double\", \
+                    \"size\" : 8, \
+                    \"alias\" : \"double\" \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Slong\", \
+                    \"size\" : 8, \
+                    \"signed\" : true \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Sint\", \
+                    \"size\" : 4, \
+                    \"signed\" : true \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Short\", \
+                    \"size\" : 2, \
+                    \"signed\" : true \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Float\", \
+                    \"size\" : 4, \
+                    \"alias\" : \"float\" \
+                }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"structA\", \
+                    \"fields\" : [{\
+                        \"name\" : \"a\", \
+                        \"type\" : \"Double\" \
+                    }, {\
+                        \"name\" : \"b\", \
+                        \"type\" : \"Slong\" \
+                    }, {\
+                        \"name\" : \"c\", \
+                        \"type\" : \"Sint\" \
+                    }, {\
+                        \"name\" : \"d\", \
+                        \"type\" : \"Short\" \
+                    }, {\
+                        \"name\" : \"e\", \
+                        \"type\" : \"Float\" \
+                    }]\
+                }], \
+                \"messages\" : {} \
+            }";
+
+static const char *avpr_example1_fqn = "test.ns.structA";
+
 const char *example1_input = "{ \
     \"a\" : 1.0, \
     \"b\" : 22, \
@@ -63,7 +118,7 @@ struct example1 {
 };
 
 static void check_example1(void *data) {
-	struct example1 *ex = (struct example1 *)data;
+	auto ex = static_cast<example1*>(data);
 	CHECK_EQUAL(1.0, ex->a);
 	LONGS_EQUAL(22, ex->b);
 	LONGS_EQUAL(32, ex->c);
@@ -74,6 +129,58 @@ static void check_example1(void *data) {
 /*********** example 2 ************************/
 const char *example2_descriptor = "{BJJDFD byte long1 long2 double1 float1 double2}";
 
+static const char *avpr_example2_descriptor = "{\
+                \"protocol\" : \"types\", \
+                \"namespace\" : \"test.ns\", \
+                \"version\" : \"1.0.0\", \
+                \"types\" : [ { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Byte\", \
+                    \"size\" : 1, \
+                    \"signed\" : true \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Slong\", \
+                    \"size\" : 8, \
+                    \"signed\" : true \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Double\", \
+                    \"size\" : 8, \
+                    \"alias\" : \"double\" \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Float\", \
+                    \"size\" : 4, \
+                    \"alias\" : \"float\" \
+                }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"structB\", \
+                    \"fields\" : [{\
+                        \"name\" : \"byte\", \
+                        \"type\" : \"Byte\" \
+                    }, {\
+                        \"name\" : \"long1\", \
+                        \"type\" : \"Slong\" \
+                    }, {\
+                        \"name\" : \"long2\", \
+                        \"type\" : \"Slong\" \
+                    }, {\
+                        \"name\" : \"double1\", \
+                        \"type\" : \"Double\" \
+                    }, {\
+                        \"name\" : \"float1\", \
+                        \"type\" : \"Float\" \
+                    }, {\
+                        \"name\" : \"double2\", \
+                        \"type\" : \"Double\" \
+                    }]\
+                }], \
+                \"messages\" : {} \
+            }";
+
+static const char *avpr_example2_fqn = "test.ns.structB";
+
 const char *example2_input = "{ \
     \"byte\" : 42, \
     \"long1\" : 232, \
@@ -93,7 +200,7 @@ struct example2 {
 };
 
 static void check_example2(void *data) {
-	struct example2 *ex = (struct example2 *)data;
+    auto ex = static_cast<example2*>(data);
 	CHECK_EQUAL(42, ex->byte);
 	LONGS_EQUAL(232, ex->long1);
 	LONGS_EQUAL(242, ex->long2);
@@ -107,6 +214,32 @@ static void check_example2(void *data) {
 /** sequence with a simple type **************/
 const char *example3_descriptor = "{[I numbers}";
 
+static const char *avpr_example3_descriptor = "{\
+                \"protocol\" : \"types\", \
+                \"namespace\" : \"test.ns\", \
+                \"version\" : \"1.0.0\", \
+                \"types\" : [ { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Sint\", \
+                    \"size\" : 4, \
+                    \"signed\" : true \
+                }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"structC\", \
+                    \"fields\" : [{\
+                        \"name\" : \"numbers\", \
+                        \"type\" : {\
+                            \"type\" : \"array\", \
+                            \"items\" : \"Sint\", \
+                            \"static\" : 3 \
+                        }\
+                    }]\
+                }], \
+                \"messages\" : {} \
+            }";
+
+static const char *avpr_example3_fqn = "test.ns.structC";
+
 const char *example3_input = "{ \
     \"numbers\" : [22,32,42] \
 }";
@@ -120,7 +253,7 @@ struct example3 {
 };
 
 static void check_example3(void *data) {
-	struct example3 *ex = (struct example3 *)data;
+    auto ex = static_cast<example3*>(data);
 	CHECK_EQUAL(3, ex->numbers.len);
 	CHECK_EQUAL(22, ex->numbers.buf[0]);
 	CHECK_EQUAL(32, ex->numbers.buf[1]);
@@ -131,6 +264,50 @@ static void check_example3(void *data) {
 /** structs within a struct (by reference)*******/
 const char *example4_descriptor = "{{IDD index val1 val2}{IDD index val1 val2} left right}";
 
+static const char *avpr_example4_descriptor = "{\
+                \"protocol\" : \"types\", \
+                \"namespace\" : \"test.ns\", \
+                \"version\" : \"1.0.0\", \
+                \"types\" : [ { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Int32\", \
+                    \"size\" : 4, \
+                    \"signed\" : true \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Double\", \
+                    \"size\" : 8, \
+                    \"alias\" : \"double\" \
+                }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"leaf\", \
+                    \"namespace\" : \"details\", \
+                    \"fields\" : [{\
+                        \"name\" : \"index\", \
+                        \"type\" : \"test.ns.Int32\" \
+                    }, {\
+                        \"name\" : \"val1\", \
+                        \"type\" : \"test.ns.Double\" \
+                    }, {\
+                        \"name\" : \"val2\", \
+                        \"type\" : \"test.ns.Double\" \
+                    }]\
+                }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"structD\", \
+                    \"fields\" : [{\
+                        \"name\" : \"left\", \
+                        \"type\" : \"details.leaf\" \
+                    }, {\
+                        \"name\" : \"right\", \
+                        \"type\" : \"details.leaf\" \
+                    }]\
+                }], \
+                \"messages\" : {} \
+            }";
+
+static const char *avpr_example4_fqn = "test.ns.structD";
+
 static const char *example4_input =  "{ \
     \"left\" : {\"index\":1, \"val1\":1.0, \"val2\":2.0 }, \
     \"right\" : {\"index\":2, \"val1\":5.0, \"val2\":4.0 } \
@@ -148,7 +325,7 @@ struct example4 {
 };
 
 static void check_example4(void *data) {
-	struct example4 *ex = (struct example4 *)data;
+    auto ex = static_cast<example4*>(data);
 	CHECK_EQUAL(1, ex->left.index);
 	CHECK_EQUAL(1.0, ex->left.val1);
 	CHECK_EQUAL(2.0, ex->left.val2);
@@ -162,12 +339,72 @@ static void check_example4(void *data) {
 /** structs within a struct (by reference)*******/
 const char *example5_descriptor = "Tleaf={ts name age};Tnode={Lnode;Lnode;Lleaf; left right value};{Lnode; head}";
 
+static const char *avpr_example5_descriptor = "{\
+                \"protocol\" : \"types\", \
+                \"namespace\" : \"test.ns\", \
+                \"version\" : \"1.0.0\", \
+                \"types\" : [ { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Char\", \
+                    \"size\" : 2 \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Str\", \
+                    \"size\" : 8, \
+                    \"alias\" : \"string\" \
+                }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"leaf\", \
+                    \"namespace\" : \"details\", \
+                    \"fields\" : [{\
+                        \"name\" : \"name\", \
+                        \"type\" : \"test.ns.Str\" \
+                    }, {\
+                        \"name\" : \"age\", \
+                        \"type\" : \"test.ns.Char\" \
+                    }]\
+                }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"node\", \
+                    \"fields\" : [{\
+                        \"name\" : \"left\", \
+                        \"type\" : \"node\", \
+                        \"ptr\" : true \
+                    }, {\
+                        \"name\" : \"right\", \
+                        \"type\" : \"node\", \
+                        \"ptr\" : true \
+                    }, {\
+                        \"name\" : \"value\", \
+                        \"type\" : \"details.leaf\", \
+                        \"ptr\" : true \
+                    }]\
+                }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"structE\", \
+                    \"fields\" : [{\
+                        \"name\" : \"head\", \
+                        \"type\" : \"node\", \
+                        \"ptr\" : true \
+                    }]\
+                }], \
+                \"messages\" : {} \
+            }";
+
+static const char *avpr_example5_fqn = "test.ns.structE";
+
 static const char *example5_input =  "{ \
     \"head\" : {\
         \"left\" : {\
             \"value\" : {\
                 \"name\" : \"John\",\
                 \"age\" : 44 \
+            },\
+            \"left\" : {\
+                \"value\" : {\
+                    \"name\" : \"Victor\",\
+                    \"age\" : 400 \
+                }\
             }\
         },\
         \"right\" : {\
@@ -195,27 +432,68 @@ struct example5 {
 };
 
 static void check_example5(void *data) {
-	struct example5 *ex = (struct example5 *)data;
-	CHECK_TRUE(ex->head != NULL);
+    auto ex = static_cast<example5*>(data);
+	CHECK_TRUE(ex->head != nullptr);
 
-	CHECK(ex->head->left != NULL);
-	CHECK(ex->head->left->value != NULL);
+	CHECK(ex->head->left != nullptr);
+	CHECK(ex->head->left->value != nullptr);
 	STRCMP_EQUAL("John", ex->head->left->value->name);
 	CHECK_EQUAL(44, ex->head->left->value->age);
-	CHECK(ex->head->left->left == NULL);
-	CHECK(ex->head->left->right == NULL);
-
-	CHECK(ex->head->right != NULL);
-	CHECK(ex->head->right->value != NULL);
+	CHECK(ex->head->left->right == nullptr);
+	CHECK(ex->head->left->left != nullptr);
+	CHECK(ex->head->left->left->value != nullptr);
+	STRCMP_EQUAL("Victor", ex->head->left->left->value->name);
+	CHECK_EQUAL(400, ex->head->left->left->value->age);
+
+	CHECK(ex->head->right != nullptr);
+	CHECK(ex->head->right->value != nullptr);
 	STRCMP_EQUAL("Peter", ex->head->right->value->name);
 	CHECK_EQUAL(55, ex->head->right->value->age);
-	CHECK(ex->head->right->left == NULL);
-	CHECK(ex->head->right->right == NULL);
+	CHECK(ex->head->right->left == nullptr);
+	CHECK(ex->head->right->right == nullptr);
 }
 
+/*********** example 6 ************************/
 static const char *example6_descriptor = "Tsample={DD v1 v2};[lsample;";
 
-static const char *example6_input = "[{\"v1\":0.1,\"v2\":0.2},{\"v1\":1.1,\"v2\":1.2},{\"v1\":2.1,\"v2\":2.2}]";
+static const char *avpr_example6_descriptor = "{\
+                \"protocol\" : \"types\", \
+                \"namespace\" : \"test.ns\", \
+                \"version\" : \"1.0.0\", \
+                \"types\" : [ { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Double\", \
+                    \"alias\" : \"double\", \
+                    \"size\" : 8 \
+                }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"sample\", \
+                    \"fields\" : [{\
+                        \"name\" : \"v1\", \
+                        \"type\" : \"Double\" \
+                    }, {\
+                        \"name\" : \"v2\", \
+                        \"type\" : \"Double\" \
+                    }]\
+                }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"structF\", \
+                    \"fields\" : [{\
+                        \"name\" : \"samples\", \
+                        \"type\" : { \
+                            \"type\" : \"array\",\
+                            \"items\" : \"sample\"\
+                        }\
+                    }]\
+                }], \
+                \"messages\" : {} \
+            }";
+static const char *avpr_example6_fqn = "test.ns.structF";
+
+static const char *example6_input = R"([{"v1":0.1,"v2":0.2},{"v1":1.1,"v2":1.2},{"v1":2.1,"v2":2.2}])";
+static const char *avpr_example6_input = R"({
+    "samples" : [{"v1":0.1,"v2":0.2},{"v1":1.1,"v2":1.2},{"v1":2.1,"v2":2.2}]
+})";
 
 struct ex6_sample {
 	double v1;
@@ -228,6 +506,10 @@ struct ex6_sequence {
 	struct ex6_sample *buf;
 };
 
+struct ex6_avpr_struct {
+    struct ex6_sequence samples;
+};
+
 static void check_example6(struct ex6_sequence seq) {
 	CHECK_EQUAL(3, seq.cap);
 	CHECK_EQUAL(3, seq.len);
@@ -239,10 +521,44 @@ static void check_example6(struct ex6_sequence seq) {
 	CHECK_EQUAL(2.2, seq.buf[2].v2);
 }
 
+static void check_example6_avpr(void *data) {
+    auto ex = static_cast<ex6_avpr_struct*>(data);
+	CHECK_EQUAL(3, ex->samples.cap);
+	CHECK_EQUAL(3, ex->samples.len);
+	CHECK_EQUAL(0.1, ex->samples.buf[0].v1);
+	CHECK_EQUAL(0.2, ex->samples.buf[0].v2);
+	CHECK_EQUAL(1.1, ex->samples.buf[1].v1);
+	CHECK_EQUAL(1.2, ex->samples.buf[1].v2);
+	CHECK_EQUAL(2.1, ex->samples.buf[2].v1);
+	CHECK_EQUAL(2.2, ex->samples.buf[2].v2);
+}
 
 /*********** example 7 ************************/
 const char *example7_descriptor = "{t a}";
 
+static const char *avpr_example7_descriptor = "{\
+                \"protocol\" : \"types\", \
+                \"namespace\" : \"test.ns\", \
+                \"version\" : \"1.0.0\", \
+                \"types\" : [ { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Str\", \
+                    \"size\" : 8, \
+                    \"alias\" : \"string\" \
+                }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"structG\", \
+                    \"fields\" : [{\
+                        \"name\" : \"a\", \
+                        \"type\" : \"Str\" \
+                    }]\
+                }], \
+                \"messages\" : {} \
+            }";
+
+
+static const char *avpr_example7_fqn = "test.ns.structG";
+
 const char *example7_input = "{ \
     \"a\" : \"apache celix\" \
 }";
@@ -252,7 +568,7 @@ struct example7 {
 };
 
 static void check_example7(void *data) {
-	struct example7 *ex = (struct example7 *)data;
+    auto ex = static_cast<example7*>(data);
 	STRCMP_EQUAL("apache celix", ex->a);
 }
 
@@ -261,6 +577,66 @@ static void check_example7(void *data) {
 
 const char *example8_descriptor = "{ZbijNP a b c d e f}";
 
+static const char *avpr_example8_descriptor = "{\
+                \"protocol\" : \"types\", \
+                \"namespace\" : \"test.ns\", \
+                \"version\" : \"1.0.0\", \
+                \"types\" : [ { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Bool\", \
+                    \"alias\" : \"boolean\", \
+                    \"size\" : 1 \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"UChar\", \
+                    \"size\" : 1 \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Uint\", \
+                    \"size\" : 4 \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Ulong\", \
+                    \"size\" : 8 \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Sint\", \
+                    \"size\" : 4, \
+                    \"signed\" : true \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"VoidPtr\", \
+                    \"size\" : 1, \
+                    \"alias\" : \"void_ptr\" \
+                }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"structH\", \
+                    \"fields\" : [{\
+                        \"name\" : \"a\", \
+                        \"type\" : \"Bool\" \
+                    }, {\
+                        \"name\" : \"b\", \
+                        \"type\" : \"UChar\" \
+                    }, {\
+                        \"name\" : \"c\", \
+                        \"type\" : \"Uint\" \
+                    }, {\
+                        \"name\" : \"d\", \
+                        \"type\" : \"Ulong\" \
+                    }, {\
+                        \"name\" : \"e\", \
+                        \"type\" : \"Sint\" \
+                    }, {\
+                        \"name\" : \"f\", \
+                        \"type\" : \"VoidPtr\" \
+                    }]\
+                }], \
+                \"messages\" : {} \
+            }";
+
+
+static const char *avpr_example8_fqn = "test.ns.structH";
+
 const char *example8_input = "{ \
     \"a\" : true, \
     \"b\" : 4, \
@@ -279,24 +655,212 @@ struct example8 {
 };
 
 static void check_example8(void *data) {
-	struct example8 *ex = (struct example8 *)data;
+    auto ex = static_cast<example8*>(data);
 	CHECK_EQUAL(true,ex->a);
 	CHECK_EQUAL(4,ex->b);
 	CHECK_EQUAL(8,ex->c);
 	//error on mac CHECK_EQUAL(16,ex->d);
-    CHECK(16 == ex->d)
+    CHECK(16 == ex->d);
 	CHECK_EQUAL(32,ex->e);
 }
 
+/*********** example 9 ************************/
+const char *example9_descriptor = "{It#OK=0;#NOK=1;#MAYBE=2;E id name result}";
+
+static const char *avpr_example9_descriptor = "{\
+                \"protocol\" : \"types\", \
+                \"namespace\" : \"test.ns\", \
+                \"version\" : \"2.0.0\", \
+                \"types\" : [ { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Sint\", \
+                    \"size\" : 4, \
+                    \"signed\" : true \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"String\", \
+                    \"alias\" : \"string\", \
+                    \"size\" : 8 \
+                }, { \
+                    \"type\" : \"enum\", \
+                    \"name\" : \"ResultEnum\", \
+                    \"EnumValues\" : [ \"OK = 0\", \"NOK=  1\", \"MAYBE  =2\" ],\
+                    \"symbols\" : [\"OK\", \"NOK\", \"MAYBE\" ]\
+                }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"structI\", \
+                    \"fields\" : [{\
+                        \"name\" : \"id\", \
+                        \"type\" : \"Sint\" \
+                    }, {\
+                        \"name\" : \"name\", \
+                        \"type\" : \"String\" \
+                    }, {\
+                        \"name\" : \"result\", \
+                        \"type\" : \"ResultEnum\" \
+                    }]\
+                }], \
+                \"messages\" : {} \
+            }";
+
+static const char *avpr_example9_fqn = "test.ns.structI";
+
+const char *example9_input_1 = "{\
+                                \"id\"   : 1000, \
+                                \"name\" : \"my_name\", \
+                                \"result\" : \"NOK\" \
+                                }";
+
+const char *example9_input_2 = "{\
+                                \"id\"   : 1001, \
+                                \"name\" : \"your_name\", \
+                                \"result\" : \"MAYBE\" \
+                                }";
+
+const char *example9_input_3 =
+        R"({
+            "id" : 1001,
+            "name" : "your_name",
+            "result" : "OK"
+        })";
+
+enum ResultEnum {
+    RE_OK = 0,
+    RE_NOK = 1,
+    RE_MAYBE = 2
+};
+
+struct example9 {
+    int32_t id;
+    char * name;
+    enum ResultEnum result;
+};
+
+static void check_example9_1(void *data) {
+    auto ex = static_cast<example9*>(data);
+    CHECK_EQUAL(1000, ex->id);
+    STRCMP_EQUAL("my_name", ex->name);
+    CHECK_EQUAL(RE_NOK, ex->result);
+}
+
+static void check_example9_2(void *data) {
+    auto ex = static_cast<example9*>(data);
+    CHECK_EQUAL(1001, ex->id);
+    STRCMP_EQUAL("your_name", ex->name);
+    CHECK_EQUAL(RE_MAYBE, ex->result);
+}
+
+static void check_example9_3(void *data) {
+    auto ex = static_cast<example9*>(data);
+    CHECK_EQUAL(1001, ex->id);
+    STRCMP_EQUAL("your_name", ex->name);
+    CHECK_EQUAL(RE_OK, ex->result);
+}
 
-static void parseTests(void) {
+static void parseAvprTests() {
+	dyn_type *type;
+	void *inst;
+    int rc;
+
+    inst = nullptr;
+    type = dynType_parseAvprWithStr(avpr_example1_descriptor, avpr_example1_fqn);
+    CHECK(type != nullptr);
+	rc = jsonSerializer_deserialize(type, example1_input, &inst);
+	CHECK_EQUAL(0, rc);
+	check_example1(inst);
+	dynType_free(type, inst);
+	dynType_destroy(type);
+
+    inst = nullptr;
+    type = dynType_parseAvprWithStr(avpr_example2_descriptor, avpr_example2_fqn);
+    CHECK(type != nullptr);
+	rc = jsonSerializer_deserialize(type, example2_input, &inst);
+	CHECK_EQUAL(0, rc);
+	check_example2(inst);
+	dynType_free(type, inst);
+	dynType_destroy(type);
+
+    inst = nullptr;
+    type = dynType_parseAvprWithStr(avpr_example3_descriptor, avpr_example3_fqn);
+    CHECK(type != nullptr);
+	rc = jsonSerializer_deserialize(type, example3_input, &inst);
+	CHECK_EQUAL(0, rc);
+	check_example3(inst);
+	dynType_free(type, inst);
+	dynType_destroy(type);
+
+    inst = nullptr;
+    type = dynType_parseAvprWithStr(avpr_example4_descriptor, avpr_example4_fqn);
+    CHECK(type != nullptr);
+	rc = jsonSerializer_deserialize(type, example4_input, &inst);
+	CHECK_EQUAL(0, rc);
+	check_example4(inst);
+	dynType_free(type, inst);
+	dynType_destroy(type);
+
+    inst = nullptr;
+    type = dynType_parseAvprWithStr(avpr_example5_descriptor, avpr_example5_fqn);
+    CHECK(type != nullptr);
+	rc = jsonSerializer_deserialize(type, example5_input, &inst);
+	CHECK_EQUAL(0, rc);
+	check_example5(inst);
+	dynType_free(type, inst);
+	dynType_destroy(type);
+
+    // Test 6 has custom checker because avdl does not allow an array to be a type on its own
+    inst = nullptr;
+    type = dynType_parseAvprWithStr(avpr_example6_descriptor, avpr_example6_fqn);
+    CHECK(type != nullptr);
+	rc = jsonSerializer_deserialize(type, avpr_example6_input, &inst);
+	CHECK_EQUAL(0, rc);
+	check_example6_avpr(inst);
+	dynType_free(type, inst);
+	dynType_destroy(type);
+
+    inst = nullptr;
+    type = dynType_parseAvprWithStr(avpr_example7_descriptor, avpr_example7_fqn);
+    CHECK(type != nullptr);
+	rc = jsonSerializer_deserialize(type, example7_input, &inst);
+	CHECK_EQUAL(0, rc);
+	check_example7(inst);
+	dynType_free(type, inst);
+	dynType_destroy(type);
+
+    inst = nullptr;
+    type = dynType_parseAvprWithStr(avpr_example8_descriptor, avpr_example8_fqn);
+    CHECK(type != nullptr);
+	rc = jsonSerializer_deserialize(type, example8_input, &inst);
+	CHECK_EQUAL(0, rc);
+	check_example8(inst);
+	dynType_free(type, inst);
+	dynType_destroy(type);
+
+    inst = nullptr;
+    type = dynType_parseAvprWithStr(avpr_example9_descriptor, avpr_example9_fqn);
+    CHECK(type != nullptr);
+	rc = jsonSerializer_deserialize(type, example9_input_1, &inst);
+	CHECK_EQUAL(0, rc);
+	check_example9_1(inst);
+	dynType_free(type, inst);
+	rc = jsonSerializer_deserialize(type, example9_input_2, &inst);
+	CHECK_EQUAL(0, rc);
+	check_example9_2(inst);
+	dynType_free(type, inst);
+    rc = jsonSerializer_deserialize(type, example9_input_3, &inst);
+    CHECK_EQUAL(0, rc);
+    check_example9_3(inst);
+    dynType_free(type, inst);
+	dynType_destroy(type);
+}
+
+static void parseTests() {
 	dyn_type *type;
 	void *inst;
 	int rc;
 
-	type = NULL;
-	inst = NULL;
-	rc = dynType_parseWithStr(example1_descriptor, NULL, NULL, &type);
+	type = nullptr;
+	inst = nullptr;
+	rc = dynType_parseWithStr(example1_descriptor, nullptr, nullptr, &type);
 	CHECK_EQUAL(0, rc);
 	rc = jsonSerializer_deserialize(type, example1_input, &inst);
 	CHECK_EQUAL(0, rc);
@@ -304,9 +868,9 @@ static void parseTests(void) {
 	dynType_free(type, inst);
 	dynType_destroy(type);
 
-	type = NULL;
-	inst = NULL;
-	rc = dynType_parseWithStr(example2_descriptor, NULL, NULL, &type);
+	type = nullptr;
+	inst = nullptr;
+	rc = dynType_parseWithStr(example2_descriptor, nullptr, nullptr, &type);
 	CHECK_EQUAL(0, rc);
 	rc = jsonSerializer_deserialize(type, example2_input, &inst);
 	CHECK_EQUAL(0, rc);
@@ -314,9 +878,9 @@ static void parseTests(void) {
 	dynType_free(type, inst);
 	dynType_destroy(type);
 
-	type = NULL;
-	inst = NULL;
-	rc = dynType_parseWithStr(example3_descriptor, NULL, NULL, &type);
+	type = nullptr;
+	inst = nullptr;
+	rc = dynType_parseWithStr(example3_descriptor, nullptr, nullptr, &type);
 	CHECK_EQUAL(0, rc);
 	rc = jsonSerializer_deserialize(type, example3_input, &inst);
 	CHECK_EQUAL(0, rc);
@@ -324,9 +888,9 @@ static void parseTests(void) {
 	dynType_free(type, inst);
 	dynType_destroy(type);
 
-	type = NULL;
-	inst = NULL;
-	rc = dynType_parseWithStr(example4_descriptor, NULL, NULL, &type);
+	type = nullptr;
+	inst = nullptr;
+	rc = dynType_parseWithStr(example4_descriptor, nullptr, nullptr, &type);
 	CHECK_EQUAL(0, rc);
 	rc = jsonSerializer_deserialize(type, example4_input, &inst);
 	CHECK_EQUAL(0, rc);
@@ -334,9 +898,9 @@ static void parseTests(void) {
 	dynType_free(type, inst);
 	dynType_destroy(type);
 
-	type = NULL;
-	inst = NULL;
-	rc = dynType_parseWithStr(example5_descriptor, NULL, NULL, &type);
+	type = nullptr;
+	inst = nullptr;
+	rc = dynType_parseWithStr(example5_descriptor, nullptr, nullptr, &type);
 	CHECK_EQUAL(0, rc);
 	rc = jsonSerializer_deserialize(type, example5_input, &inst);
 	CHECK_EQUAL(0, rc);
@@ -344,9 +908,9 @@ static void parseTests(void) {
 	dynType_free(type, inst);
 	dynType_destroy(type);
 
-	type = NULL;
+	type = nullptr;
 	struct ex6_sequence *seq;
-	rc = dynType_parseWithStr(example6_descriptor, NULL, NULL, &type);
+	rc = dynType_parseWithStr(example6_descriptor, nullptr, nullptr, &type);
 	CHECK_EQUAL(0, rc);
 	rc = jsonSerializer_deserialize(type, example6_input, (void **)&seq);
 	CHECK_EQUAL(0, rc);
@@ -354,10 +918,9 @@ static void parseTests(void) {
 	dynType_free(type, seq);
 	dynType_destroy(type);
 
-
-	type = NULL;
-	inst = NULL;
-	rc = dynType_parseWithStr(example7_descriptor, NULL, NULL, &type);
+	type = nullptr;
+	inst = nullptr;
+	rc = dynType_parseWithStr(example7_descriptor, nullptr, nullptr, &type);
 	CHECK_EQUAL(0, rc);
 	rc = jsonSerializer_deserialize(type, example7_input, &inst);
 	CHECK_EQUAL(0, rc);
@@ -365,19 +928,140 @@ static void parseTests(void) {
 	dynType_free(type, inst);
 	dynType_destroy(type);
 
-	type = NULL;
-	inst = NULL;
-	rc = dynType_parseWithStr(example8_descriptor, NULL, NULL, &type);
+	type = nullptr;
+	inst = nullptr;
+	rc = dynType_parseWithStr(example8_descriptor, nullptr, nullptr, &type);
 	CHECK_EQUAL(0, rc);
 	rc = jsonSerializer_deserialize(type, example8_input, &inst);
 	CHECK_EQUAL(0, rc);
 	check_example8(inst);
 	dynType_free(type, inst);
 	dynType_destroy(type);
+
+	type = nullptr;
+	inst = nullptr;
+	rc = dynType_parseWithStr(example9_descriptor, nullptr, nullptr, &type);
+	CHECK_EQUAL(0, rc);
+	rc = jsonSerializer_deserialize(type, example9_input_1, &inst);
+	CHECK_EQUAL(0, rc);
+	check_example9_1(inst);
+	dynType_free(type, inst);
+	rc = jsonSerializer_deserialize(type, example9_input_2, &inst);
+	CHECK_EQUAL(0, rc);
+	check_example9_2(inst);
+	dynType_free(type, inst);
+	dynType_destroy(type);
 }
 
+/*********** write example 1 ************************/
 const char *write_example1_descriptor = "{BSIJsijFDNZb a b c d e f g h i j k l}";
 
+const char *avpr_write_example1_descriptor = "{\
+                \"protocol\" : \"types\", \
+                \"namespace\" : \"test.ns\", \
+                \"version\" : \"1.0.0\", \
+                \"types\" : [ { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"SChar\", \
+                    \"signed\" : true, \
+                    \"size\" : 1 \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Short\", \
+                    \"size\" : 2, \
+                    \"signed\" : true \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Sint\", \
+                    \"size\" : 4, \
+                    \"signed\" : true \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Slong\", \
+                    \"size\" : 8, \
+                    \"signed\" : true \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"UShort\", \
+                    \"size\" : 2 \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Uint\", \
+                    \"size\" : 4 \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Ulong\", \
+                    \"size\" : 8 \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Float\", \
+                    \"size\" : 4, \
+                    \"alias\" : \"float\" \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Double\", \
+                    \"size\" : 8, \
+                    \"alias\" : \"double\" \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"NativeInt\", \
+                    \"size\" : 4, \
+                    \"alias\" : \"native_int\" \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Bool\", \
+                    \"size\" : 1, \
+                    \"alias\" : \"boolean\" \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"UChar\", \
+                    \"size\" : 1 \
+                }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"structAW\", \
+                    \"fields\" : [{\
+                        \"name\" : \"a\", \
+                        \"type\" : \"SChar\" \
+                    }, {\
+                        \"name\" : \"b\", \
+                        \"type\" : \"Short\" \
+                    }, {\
+                        \"name\" : \"c\", \
+                        \"type\" : \"Sint\" \
+                    }, {\
+                        \"name\" : \"d\", \
+                        \"type\" : \"Slong\" \
+                    }, {\
+                        \"name\" : \"e\", \
+                        \"type\" : \"UShort\" \
+                    }, {\
+                        \"name\" : \"f\", \
+                        \"type\" : \"Uint\" \
+                    }, {\
+                        \"name\" : \"g\", \
+                        \"type\" : \"Ulong\" \
+                    }, {\
+                        \"name\" : \"h\", \
+                        \"type\" : \"Float\" \
+                    }, {\
+                        \"name\" : \"i\", \
+                        \"type\" : \"Double\" \
+                    }, {\
+                        \"name\" : \"j\", \
+                        \"type\" : \"NativeInt\" \
+                    }, {\
+                        \"name\" : \"k\", \
+                        \"type\" : \"Bool\" \
+                    }, {\
+                        \"name\" : \"l\", \
+                        \"type\" : \"UChar\" \
+                    }]\
+                }], \
+                \"messages\" : {} \
+            }";
+
+const char *avpr_write_example1_fqn = "test.ns.structAW";
+
 struct write_example1 {
 	char a;
 	int16_t b;
@@ -394,71 +1078,133 @@ struct write_example1 {
 };
 
 void writeTest1(void) {
-	struct write_example1 ex1;
-	ex1.a=1;
-	ex1.b=2;
-	ex1.c=3;
-	ex1.d=4;
-	ex1.e=5;
-	ex1.f=6;
-	ex1.g=7;
-	ex1.h=8.8f;
-	ex1.i=9.9;
-	ex1.j=10;
-	ex1.k=true;
-	ex1.l=12;
-
-	dyn_type *type = NULL;
-	char *result = NULL;
-	int rc = dynType_parseWithStr(write_example1_descriptor, "ex1", NULL, &type);
+	write_example1 ex1 {'A',2,3,4,5,6,7,8.8f,9.9,10,true,12};
+	ex1.k = !ex1.k;
+
+	dyn_type *type = nullptr;
+	char *result = nullptr;
+	int rc = dynType_parseWithStr(write_example1_descriptor, "ex1", nullptr, &type);
 	CHECK_EQUAL(0, rc);
 	rc = jsonSerializer_serialize(type, &ex1, &result);
 	CHECK_EQUAL(0, rc);
-	STRCMP_CONTAINS("\"a\":1", result);
-	STRCMP_CONTAINS("\"b\":2", result);
-	STRCMP_CONTAINS("\"c\":3", result);
-	STRCMP_CONTAINS("\"d\":4", result);
-	STRCMP_CONTAINS("\"e\":5", result);
-	STRCMP_CONTAINS("\"f\":6", result);
-	STRCMP_CONTAINS("\"g\":7", result);
-	STRCMP_CONTAINS("\"h\":8.8", result);
-	STRCMP_CONTAINS("\"i\":9.9", result);
-	STRCMP_CONTAINS("\"j\":10", result);
-	STRCMP_CONTAINS("\"k\":true", result);
-	STRCMP_CONTAINS("\"l\":12", result);
+	STRCMP_CONTAINS(R"("a":65)", result);
+	STRCMP_CONTAINS(R"("b":2)", result);
+	STRCMP_CONTAINS(R"("c":3)", result);
+	STRCMP_CONTAINS(R"("d":4)", result);
+	STRCMP_CONTAINS(R"("e":5)", result);
+	STRCMP_CONTAINS(R"("f":6)", result);
+	STRCMP_CONTAINS(R"("g":7)", result);
+	STRCMP_CONTAINS(R"("h":8.8)", result);
+	STRCMP_CONTAINS(R"("i":9.9)", result);
+	STRCMP_CONTAINS(R"("j":10)", result);
+	STRCMP_CONTAINS(R"("k":false)", result);
+	STRCMP_CONTAINS(R"("l":12)", result);
 	//printf("example 1 result: '%s'\n", result);
 	dynType_destroy(type);
 	free(result);
 }
 
+void writeAvprTest1(void) {
+	write_example1 ex1 {1,2,3,4,5,6,7,8.8f,9.9,10,true,12};
+
+	char *result = nullptr;
+	dyn_type *type = dynType_parseAvprWithStr(avpr_write_example1_descriptor, avpr_write_example1_fqn);
+	CHECK(type != nullptr);
+
+	int rc = jsonSerializer_serialize(type, &ex1, &result);
+	CHECK_EQUAL(0, rc);
+
+	STRCMP_CONTAINS(R"("a":1)", result);
+	STRCMP_CONTAINS(R"("b":2)", result);
+	STRCMP_CONTAINS(R"("c":3)", result);
+	STRCMP_CONTAINS(R"("d":4)", result);
+	STRCMP_CONTAINS(R"("e":5)", result);
+	STRCMP_CONTAINS(R"("f":6)", result);
+	STRCMP_CONTAINS(R"("g":7)", result);
+	STRCMP_CONTAINS(R"("h":8.8)", result);
+	STRCMP_CONTAINS(R"("i":9.9)", result);
+	STRCMP_CONTAINS(R"("j":10)", result);
+	STRCMP_CONTAINS(R"("k":true)", result);
+	STRCMP_CONTAINS(R"("l":12)", result);
+
+	dynType_destroy(type);
+	free(result);
+}
+
+/*********** write example 2 ************************/
 const char *write_example2_descriptor = "{*{JJ a b}{SS c d} sub1 sub2}";
 
+const char *avpr_write_example2_descriptor = "{\
+                \"protocol\" : \"types\", \
+                \"namespace\" : \"test.ns\", \
+                \"version\" : \"1.0.0\", \
+                \"types\" : [ { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Short\", \
+                    \"size\" : 2, \
+                    \"signed\" : true \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Slong\", \
+                    \"size\" : 8, \
+                    \"signed\" : true \
+                }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"SubPtr\", \
+                    \"fields\" : [{\
+                        \"name\" : \"a\", \
+                        \"type\" : \"Slong\" \
+                    }, {\
+                        \"name\" : \"b\", \
+                        \"type\" : \"Slong\" \
+                    }]\
+                }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"Sub\", \
+                    \"fields\" : [{\
+                        \"name\" : \"c\", \
+                        \"type\" : \"Short\" \
+                    }, {\
+                        \"name\" : \"d\", \
+                        \"type\" : \"Short\" \
+                    }]\
+                }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"structBW\", \
+                    \"fields\" : [{\
+                        \"name\" : \"sub1\", \
+                        \"ptr\" : true, \
+                        \"type\" : \"SubPtr\" \
+                    }, {\
+                        \"name\" : \"sub2\", \
+                        \"type\" : \"Sub\" \
+                    }]\
+                }], \
+                \"messages\" : {} \
+            }";
+
+const char *avpr_write_example2_fqn = "test.ns.structBW";
+
 struct write_example2_sub {
 	int64_t a;
 	int64_t b;
 };
 
 struct write_example2 {
-	struct write_example2_sub *sub1;
+	write_example2_sub *sub1;
 	struct {
 		int16_t c;
 		int16_t d;
-	} sub2;
+	};
 };
 
 void writeTest2(void) {
-	struct write_example2_sub sub1;
-	sub1.a = 1;
-	sub1.b = 2;
+	write_example2_sub sub1 {1,2};
+	write_example2 ex {&sub1, {3, 4}};
 
-	struct write_example2 ex;
-	ex.sub1=&sub1;
-	ex.sub2.c = 3;
-	ex.sub2.d = 4;
-
-	dyn_type *type = NULL;
-	char *result = NULL;
-	int rc = dynType_parseWithStr(write_example2_descriptor, "ex2", NULL, &type);
+	dyn_type *type = nullptr;
+	char *result = nullptr;
+	int rc = dynType_parseWithStr(write_example2_descriptor, "ex2", nullptr, &type);
 	CHECK_EQUAL(0, rc);
 	rc = jsonSerializer_serialize(type, &ex, &result);
 	CHECK_EQUAL(0, rc);
@@ -471,8 +1217,78 @@ void writeTest2(void) {
 	free(result);
 }
 
+void writeAvprTest2(void) {
+    write_example2_sub sub1 {0,0};
+    write_example2 ex {&sub1, {3, 4}};
+    ex.sub1->a = 1;
+    ex.sub1->b = 2;
+
+	char *result = nullptr;
+	dyn_type *type = dynType_parseAvprWithStr(avpr_write_example2_descriptor, avpr_write_example2_fqn);
+	CHECK(type != nullptr);
+
+	int rc = jsonSerializer_serialize(type, &ex, &result);
+	CHECK_EQUAL(0, rc);
+
+	STRCMP_CONTAINS("\"a\":1", result);
+	STRCMP_CONTAINS("\"b\":2", result);
+	STRCMP_CONTAINS("\"c\":3", result);
+	STRCMP_CONTAINS("\"d\":4", result);
+
+	dynType_destroy(type);
+	free(result);
+}
+
+/*********** write example 3 ************************/
 const char *write_example3_descriptor = "Tperson={ti name age};[Lperson;";
 
+const char *avpr_write_example3_descriptor = "{\
+                \"protocol\" : \"types\", \
+                \"namespace\" : \"test.ns\", \
+                \"version\" : \"1.0.0\", \
+                \"types\" : [ { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Str\", \
+                    \"size\" : 8, \
+                    \"alias\" : \"string\" \
+                }, { \
+                    \"type\" : \"fixed\", \
+                    \"name\" : \"Uint\", \
+                    \"size\" : 4 \
+                }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"PersonPtr\", \
+                    \"fields\" : [{\
+                        \"name\" : \"p\", \
+                        \"type\" : \"Person\", \
+                        \"ptr\" : true \
+                    }]\
+                }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"Person\", \
+                    \"fields\" : [{\
+                        \"name\" : \"name\", \
+                        \"type\" : \"Str\" \
+                    }, {\
+                        \"name\" : \"age\", \
+                        \"type\" : \"Uint\" \
+                    }]\
+                }, { \
+                    \"type\" : \"record\", \
+                    \"name\" : \"structCW\", \
+                    \"fields\" : [{\
+                        \"name\" : \"persons\", \
+                        \"type\" : { \
+                            \"type\" : \"array\",\
+                            \"items\" : \"PersonPtr\"\
+                        }\
+                    }]\
+                }], \
+                \"messages\" : {} \
+            }";
+
+const char *avpr_write_example3_fqn = "test.ns.structCW";
+
 struct write_example3_person {
 	const char *name;
 	uint32_t age;
@@ -481,37 +1297,24 @@ struct write_example3_person {
 struct write_example3 {
 	uint32_t cap;
 	uint32_t len;
-	struct write_example3_person **buf;
+	write_example3_person **buf;
 };
 
 void writeTest3(void) {
-	struct write_example3_person p1;
-	p1.name = "John";
-	p1.age = 33;
-
-	struct write_example3_person p2;
-	p2.name = "Peter";
-	p2.age = 44;
-
-	struct write_example3_person p3;
-	p3.name = "Carol";
-	p3.age = 55;
+	write_example3_person p1 {"John", 33};
+	write_example3_person p2 {"Peter", 44};
+	write_example3_person p3 {"Carol", 55};
+	write_example3_person p4 {"Elton", 66};
 
-	struct write_example3_person p4;
-	p4.name = "Elton";
-	p4.age = 66;
-
-	struct write_example3 seq;
-	seq.buf = (struct write_example3_person **) calloc(4, sizeof(void *));
-	seq.len = seq.cap = 4;
+	write_example3 seq {4, 4, (struct write_example3_person **) calloc(4, sizeof(void *))};
 	seq.buf[0] = &p1;
 	seq.buf[1] = &p2;
 	seq.buf[2] = &p3;
 	seq.buf[3] = &p4;
 
-	dyn_type *type = NULL;
-	char *result = NULL;
-	int rc = dynType_parseWithStr(write_example3_descriptor, "ex3", NULL, &type);
+	dyn_type *type = nullptr;
+	char *result = nullptr;
+	int rc = dynType_parseWithStr(write_example3_descriptor, "ex3", nullptr, &type);
 	CHECK_EQUAL(0, rc);
 	rc = jsonSerializer_serialize(type, &seq, &result);
 	CHECK_EQUAL(0, rc);
@@ -525,34 +1328,68 @@ void writeTest3(void) {
 	free(result);
 }
 
+void writeAvprTest3(void) {
+    write_example3_person p1 {"John", 33};
+    write_example3_person p2 {"Peter", 44};
+    write_example3_person p3 {"Carol", 55};
+    write_example3_person p4 {"Elton", 66};
+
+    write_example3 seq {4, 4, (write_example3_person **) calloc(4, sizeof(void *))};
+    seq.buf[0] = &p1;
+    seq.buf[1] = &p2;
+    seq.buf[2] = &p3;
+    seq.buf[3] = &p4;
+
+	char *result = nullptr;
+	dyn_type *type = dynType_parseAvprWithStr(avpr_write_example3_descriptor, avpr_write_example3_fqn);
+    CHECK(type != nullptr);
+
+	int rc = jsonSerializer_serialize(type, &seq, &result);
+	CHECK_EQUAL(0, rc);
 
+	STRCMP_CONTAINS("\"age\":33", result);
+	STRCMP_CONTAINS("\"age\":44", result);
+	STRCMP_CONTAINS("\"age\":55", result);
+	STRCMP_CONTAINS("\"age\":66", result);
 
+	free(seq.buf);
+	dynType_destroy(type);
+	free(result);
 }
 
+} // extern "C"
+
 TEST_GROUP(JsonSerializerTests) {
-	void setup() {
+	void setup() override {
 		int lvl = 1;
-		dynCommon_logSetup(stdLog, NULL, lvl);
-		dynType_logSetup(stdLog, NULL,lvl);
-		jsonSerializer_logSetup(stdLog, NULL, lvl);
+		dynCommon_logSetup(stdLog, nullptr, lvl);
+		dynType_logSetup(stdLog, nullptr,lvl);
+		dynAvprType_logSetup(stdLog, nullptr,lvl);
+		dynTypeCommon_logSetup(stdLog, nullptr,lvl);
+		jsonSerializer_logSetup(stdLog, nullptr, lvl);
 	}
 };
 
 TEST(JsonSerializerTests, ParseTests) {
-	//TODO split up
 	parseTests();
 }
 
+TEST(JsonSerializerTests, ParseAvprTests) {
+    parseAvprTests();
+}
+
 TEST(JsonSerializerTests, WriteTest1) {
 	writeTest1();
+    writeAvprTest1();
 }
 
 TEST(JsonSerializerTests, WriteTest2) {
 	writeTest2();
+    writeAvprTest2();
 }
 
 TEST(JsonSerializerTests, WriteTest3) {
 	writeTest3();
+    writeAvprTest3();
 }
 
-
diff --git a/libs/framework/CMakeLists.txt b/libs/framework/CMakeLists.txt
index 63844fd..461514d 100644
--- a/libs/framework/CMakeLists.txt
+++ b/libs/framework/CMakeLists.txt
@@ -80,20 +80,20 @@ if (ENABLE_TESTING AND FRAMEWORK_TESTS)
         private/mock/celix_log_mock.c)
     target_link_libraries(attribute_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)
 
-#        add_executable(bundle_archive_test 
-#            private/mock/celix_log_mock.c
-#            private/test/bundle_archive_test.cpp
-#            src/bundle_revision.c
-#            src/manifest.c
-#            src/miniunz.c
-#            src/unzip.c
-#            src/ioapi.c
-#            src/properties.c
-#            src/bundle_archive.c
-#            src/celix_errorcodes.c
-#            src/utils.c)
-#        target_link_libraries(bundle_archive_test Celix::utils ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} ${ZLIB_LIBRARY} pthread)
-
+#    add_executable(bundle_archive_test
+#        private/mock/celix_log_mock.c
+#        private/test/bundle_archive_test.cpp #TODO: fix? contains invalid casts
+#        src/bundle_revision.c
+#        src/manifest.c
+#        src/miniunz.c
+#        src/unzip.c
+#        src/ioapi.c
+#        # src/properties.c
+#        src/bundle_archive.c
+#        src/celix_errorcodes.c
+#        # src/utils.c
+#        )
+#    target_link_libraries(bundle_archive_test Celix::utils ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} ${ZLIB_LIBRARY} pthread)
 
     add_executable(bundle_cache_test
         private/test/bundle_cache_test.cpp
@@ -200,17 +200,18 @@ if (ENABLE_TESTING AND FRAMEWORK_TESTS)
         private/mock/celix_log_mock.c)
     target_link_libraries(manifest_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)
 
-#        add_executable(module_test 
-#            private/test/module_test.cpp
-#            private/mock/bundle_mock.c
-#            private/mock/version_mock.c
-#            private/mock/manifest_mock.c
-#            private/mock/manifest_parser_mock.c
-#            private/mock/capability_mock.c
-#            private/mock/requirement_mock.c
-#            private/mock/wire_mock.c
-#            src/module.c)
-#        target_link_libraries(module_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)
+#    add_executable(module_test
+#        private/test/module_test.cpp # TODO: fix invalid conversions from char ** to const char**
+#        private/mock/bundle_mock.c
+#        private/mock/version_mock.c
+#        private/mock/manifest_mock.c
+#        private/mock/manifest_parser_mock.c
+#        private/mock/capability_mock.c
+#        private/mock/requirement_mock.c
+#        private/mock/wire_mock.c
+#        src/module.c)
+#    target_link_libraries(module_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)
+#    target_include_directories(module_test SYSTEM ${CPPUTEST_INCLUDE_DIR})
 
     add_executable(requirement_test
         private/test/requirement_test.cpp
@@ -222,19 +223,19 @@ if (ENABLE_TESTING AND FRAMEWORK_TESTS)
         private/mock/celix_log_mock.c)
     target_link_libraries(requirement_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)
 
-#        add_executable(resolver_test 
-#            private/test/resolver_test.cpp
-#            private/mock/bundle_mock.c
-#            private/mock/requirement_mock.c
-#            private/mock/capability_mock.c
-#            private/mock/manifest_parser_mock.c
-#            private/mock/version_mock.c
-#            src/wire.c
-#            src/module.c
-#            src/resolver.c
-#            src/celix_errorcodes.c
-#            private/mock/celix_log_mock.c)
-#        target_link_libraries(resolver_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)
+#    add_executable(resolver_test
+#        private/test/resolver_test.cpp #TODO: fix missing include
+#        private/mock/bundle_mock.c
+#        private/mock/requirement_mock.c
+#        private/mock/capability_mock.c
+#        private/mock/manifest_parser_mock.c
+#        private/mock/version_mock.c
+#        src/wire.c
+#        src/module.c
+#        src/resolver.c
+#        src/celix_errorcodes.c
+#        private/mock/celix_log_mock.c)
+#    target_link_libraries(resolver_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)
 
     add_executable(service_reference_test
         private/test/service_reference_test.cpp
@@ -254,7 +255,6 @@ if (ENABLE_TESTING AND FRAMEWORK_TESTS)
         private/mock/celix_log_mock.c)
     target_link_libraries(service_registration_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)
 
-
     add_executable(service_registry_test
         private/test/service_registry_test.cpp
         private/mock/framework_mock.c
diff --git a/libs/framework/tst/CMakeLists.txt b/libs/framework/tst/CMakeLists.txt
index 9b7dd97..76d0990 100644
--- a/libs/framework/tst/CMakeLists.txt
+++ b/libs/framework/tst/CMakeLists.txt
@@ -28,7 +28,9 @@ add_executable(test_framework
     bundle_context_bundles_tests.cpp
     bundle_context_services_test.cpp
 )
+
 target_link_libraries(test_framework Celix::framework ${CURL_LIBRARIES} ${CPPUTEST_LIBRARY})
+
 add_dependencies(test_framework simple_test_bundle1_bundle simple_test_bundle2_bundle simple_test_bundle3_bundle simple_test_bundle4_bundle simple_test_bundle5_bundle)
 target_include_directories(test_framework PRIVATE ../src)