From 6cc27dcd98a2424df6f2ca97643f9ce3a020c9e6 Mon Sep 17 00:00:00 2001 From: Vicente Eduardo Ferrer Garcia Date: Wed, 13 Nov 2024 20:32:48 +0100 Subject: [PATCH] Extended type support for c_loader, improve search of headers and libraries for c_loader, assuming now they are not in the same folder, add test with support for pointers to pointers in c_loader. --- .../loaders/c_loader/source/c_loader_impl.cpp | 59 +++++++++++++++++-- source/scripts/c/CMakeLists.txt | 2 +- .../scripts/c/libloadtest/source/loadtest.cpp | 9 --- .../{libloadtest => loadtest}/CMakeLists.txt | 0 source/scripts/c/loadtest/source/loadtest.cpp | 39 ++++++++++++ .../source/loadtest.h | 20 +++++++ .../source/metacall_c_lib_test.cpp | 50 ++++++++++++++++ 7 files changed, 165 insertions(+), 14 deletions(-) delete mode 100644 source/scripts/c/libloadtest/source/loadtest.cpp rename source/scripts/c/{libloadtest => loadtest}/CMakeLists.txt (100%) create mode 100644 source/scripts/c/loadtest/source/loadtest.cpp rename source/scripts/c/{libloadtest => loadtest}/source/loadtest.h (54%) diff --git a/source/loaders/c_loader/source/c_loader_impl.cpp b/source/loaders/c_loader/source/c_loader_impl.cpp index 76842034d..d361c90c6 100644 --- a/source/loaders/c_loader/source/c_loader_impl.cpp +++ b/source/loaders/c_loader/source/c_loader_impl.cpp @@ -244,6 +244,7 @@ typedef struct loader_impl_c_handle_dynlink_type : loader_impl_c_handle_base_typ this->load_dynlink(lib_dir, lib_name.c_str()); + /* If the path is absolute, we assume the header is in the same folder */ if (this->lib != NULL) { return this->add_header(lib_dir, lib_name); @@ -251,6 +252,8 @@ typedef struct loader_impl_c_handle_dynlink_type : loader_impl_c_handle_base_typ } else { + bool header_found = false; + for (auto exec_path : c_impl->execution_paths) { fs::path absolute_path(exec_path); @@ -259,11 +262,23 @@ typedef struct loader_impl_c_handle_dynlink_type : loader_impl_c_handle_base_typ std::string lib_name = lib_path.filename().string(); - this->load_dynlink(absolute_path.c_str(), lib_name.c_str()); + /* If the path is relative, we keep trying the exec_paths until we find the header, + * this is for solving situations where we have the header in /usr/local/include and + * the library in /usr/local/lib + */ + if (this->lib == NULL) + { + this->load_dynlink(absolute_path, lib_name.c_str()); + } + + if (header_found == false) + { + header_found = this->add_header(absolute_path, lib_name); + } - if (this->lib != NULL) + if (this->lib != NULL && header_found == true) { - return this->add_header(absolute_path, lib_name); + return true; } } } @@ -284,7 +299,7 @@ typedef struct loader_impl_c_handle_dynlink_type : loader_impl_c_handle_base_typ } private: - void load_dynlink(fs::path path, const char *library_name) + void load_dynlink(fs::path &path, const char *library_name) { /* This function will try to check if the library exists before loading it, so we avoid error messages from dynlink when guessing the file path for relative load from file */ @@ -771,12 +786,46 @@ int c_loader_impl_initialize_types(loader_impl impl) const char *name; } type_id_name_pair[] = { { TYPE_BOOL, "bool" }, + { TYPE_CHAR, "char" }, + { TYPE_CHAR, "int8_t" }, + { TYPE_CHAR, "uint8_t" }, + { TYPE_CHAR, "int_least8_t" }, + { TYPE_CHAR, "uint_least8_t" }, + { TYPE_CHAR, "int_fast8_t" }, + { TYPE_CHAR, "uint_fast8_t" }, + { TYPE_SHORT, "short" }, + { TYPE_SHORT, "int16_t" }, + { TYPE_SHORT, "uint16_t" }, + { TYPE_SHORT, "int_least16_t" }, + { TYPE_SHORT, "uint_least16_t" }, + { TYPE_SHORT, "int_fast16_t" }, + { TYPE_SHORT, "uint_fast16_t" }, + { TYPE_INT, "int" }, + { TYPE_INT, "uint32_t" }, + { TYPE_INT, "int32_t" }, + { TYPE_INT, "int_least32_t" }, + { TYPE_INT, "uint_least32_t" }, + { TYPE_INT, "int_fast32_t" }, + { TYPE_INT, "uint_fast32_t" }, + { TYPE_LONG, "long" }, + { TYPE_LONG, "long long" }, + { TYPE_LONG, "uint64_t" }, + { TYPE_LONG, "int64_t" }, + { TYPE_LONG, "int_least64_t" }, + { TYPE_LONG, "uint_least64_t" }, + { TYPE_LONG, "int_fast64_t" }, + { TYPE_LONG, "uint_fast64_t" }, + { TYPE_LONG, "ptrdiff_t" }, + { TYPE_LONG, "intptr_t" }, + { TYPE_LONG, "uintptr_t" }, + { TYPE_FLOAT, "float" }, { TYPE_DOUBLE, "double" }, + { TYPE_INVALID, "void" } /* TODO: Do more types (and the unsigned versions too?) */ @@ -838,6 +887,8 @@ int c_loader_impl_execution_path(loader_impl impl, const loader_path path) { loader_impl_c c_impl = static_cast(loader_impl_get(impl)); + /* TODO: It would be interesting to support LD_LIBRARY_PATH or DYLD_LIBRARY_PATH + * on startup for supporting standard execution paths */ c_impl->execution_paths.push_back(path); return 0; diff --git a/source/scripts/c/CMakeLists.txt b/source/scripts/c/CMakeLists.txt index c395301ef..28cac118f 100644 --- a/source/scripts/c/CMakeLists.txt +++ b/source/scripts/c/CMakeLists.txt @@ -16,4 +16,4 @@ include(CProject) add_subdirectory(compiled) add_subdirectory(ffi) add_subdirectory(cbks) -add_subdirectory(libloadtest) +add_subdirectory(loadtest) diff --git a/source/scripts/c/libloadtest/source/loadtest.cpp b/source/scripts/c/libloadtest/source/loadtest.cpp deleted file mode 100644 index 95fb3e3df..000000000 --- a/source/scripts/c/libloadtest/source/loadtest.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "loadtest.h" -#include - -long call_cpp_func(void) -{ - std::vector v = { 7, 323, 14, 8 }; - - return v[1]; -} diff --git a/source/scripts/c/libloadtest/CMakeLists.txt b/source/scripts/c/loadtest/CMakeLists.txt similarity index 100% rename from source/scripts/c/libloadtest/CMakeLists.txt rename to source/scripts/c/loadtest/CMakeLists.txt diff --git a/source/scripts/c/loadtest/source/loadtest.cpp b/source/scripts/c/loadtest/source/loadtest.cpp new file mode 100644 index 000000000..537175040 --- /dev/null +++ b/source/scripts/c/loadtest/source/loadtest.cpp @@ -0,0 +1,39 @@ +#include "loadtest.h" +#include +#include + +long call_cpp_func(void) +{ + std::vector v = { 7, 323, 14, 8 }; + + return v[1]; +} + +int pair_list_init(pair_list **t) +{ + static const uint32_t size = 3; + + *t = new pair_list(); + + (*t)->size = size; + (*t)->pairs = new pair[(*t)->size]; + + for (uint32_t i = 0; i < size; ++i) + { + (*t)->pairs[i].i = i; + (*t)->pairs[i].d = (double)(((double)i) * 1.0); + } + + return 0; +} + +double pair_list_value(pair_list *t, uint32_t id) +{ + return t->pairs[id].d; +} + +void pair_list_destroy(pair_list *t) +{ + delete[] t->pairs; + delete t; +} diff --git a/source/scripts/c/libloadtest/source/loadtest.h b/source/scripts/c/loadtest/source/loadtest.h similarity index 54% rename from source/scripts/c/libloadtest/source/loadtest.h rename to source/scripts/c/loadtest/source/loadtest.h index 1434c2d59..85b8b28b7 100644 --- a/source/scripts/c/libloadtest/source/loadtest.h +++ b/source/scripts/c/loadtest/source/loadtest.h @@ -11,8 +11,28 @@ extern "C" { #endif +#include + +typedef struct +{ + uint32_t i; + double d; +} pair; + +typedef struct +{ + uint32_t size; + pair *pairs; +} pair_list; + EXPORT long call_cpp_func(void); +EXPORT int pair_list_init(pair_list **t); + +EXPORT double pair_list_value(pair_list *t, uint32_t id); + +EXPORT void pair_list_destroy(pair_list *t); + #ifdef __cplusplus } #endif diff --git a/source/tests/metacall_c_lib_test/source/metacall_c_lib_test.cpp b/source/tests/metacall_c_lib_test/source/metacall_c_lib_test.cpp index 01bfc4097..87fb6c75d 100644 --- a/source/tests/metacall_c_lib_test/source/metacall_c_lib_test.cpp +++ b/source/tests/metacall_c_lib_test/source/metacall_c_lib_test.cpp @@ -43,5 +43,55 @@ TEST_F(metacall_c_lib_test, DefaultConstructor) metacall_value_destroy(ret); + void *pair_list = NULL; + + void *args_init[] = { + metacall_value_create_ptr(&pair_list), + }; + + ret = metacallv("pair_list_init", args_init); + + EXPECT_NE((void *)NULL, (void *)ret); + + EXPECT_EQ((enum metacall_value_id)metacall_value_id(ret), (enum metacall_value_id)METACALL_INT); + + EXPECT_EQ((int)metacall_value_to_int(ret), (int)0); + + metacall_value_destroy(ret); + + metacall_value_destroy(args_init[0]); + + void *args_value[] = { + metacall_value_create_ptr(pair_list), + metacall_value_create_int(2) + }; + + ret = metacallv("pair_list_value", args_value); + + EXPECT_NE((void *)NULL, (void *)ret); + + EXPECT_EQ((enum metacall_value_id)metacall_value_id(ret), (enum metacall_value_id)METACALL_DOUBLE); + + EXPECT_EQ((double)metacall_value_to_double(ret), (double)2.0); + + metacall_value_destroy(ret); + + metacall_value_destroy(args_value[0]); + metacall_value_destroy(args_value[1]); + + void *args_destroy[] = { + metacall_value_create_ptr(pair_list), + }; + + ret = metacallv("pair_list_destroy", args_destroy); + + EXPECT_NE((void *)NULL, (void *)ret); + + EXPECT_EQ((enum metacall_value_id)metacall_value_id(ret), (enum metacall_value_id)METACALL_INVALID); + + metacall_value_destroy(ret); + + metacall_value_destroy(args_destroy[0]); + EXPECT_EQ((int)0, (int)metacall_destroy()); }