SET(PREFIX ${CMAKE_INSTALL_PREFIX})
SET(VERSION ${FULLVER})
+SET(LIBDIR ${LIB_INSTALL_DIR})
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
SET(TARGET_PARCEL_UNITTESTS "parcel_unittests")
SET(TARGET_TIZEN_DATABASE_UNITTESTS "tizen-database_unittests")
SET(TARGET_TIZEN_SHARED_QUEUE_UNITTESTS "tizen-shared-queue_unittests")
+SET(TARGET_TIZEN_LIBOPENER_UNITTESTS "tizen-libopener_unittests")
INCLUDE(FindPkgConfig)
INCLUDE(ApplyPkgConfig)
ADD_TEST(NAME ${TARGET_TIZEN_SHARED_QUEUE_UNITTESTS}
COMMAND ${TARGET_TIZEN_SHARED_QUEUE_UNITTESTS}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests/tizen-shared-queue_unittests)
+
+ADD_TEST(NAME ${TARGET_TIZEN_LIBOPENER_UNITTESTS}
+ COMMAND ${TARGET_TIZEN_LIBOPENER_UNITTESTS}
+ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests/tizen-libopener_unittests)
%description -n parcel-unittests
GTest for parcel
+#################################################
+## tizen-libopener-devel
+#################################################
+%package -n tizen-libopener-devel
+Summary: Tizen-libopener (devel)
+Group: Development/Libraries
+
+%description -n tizen-libopener-devel
+C++ wrapper API for dlopen and dlsym
+
+#################################################
+# tizen-libopener-unittests
+#################################################
+%package -n tizen-libopener-unittests
+Summary: GTest for tizen-libopener
+Group: Development/Libraries
+
+%description -n tizen-libopener-unittests
+GTest for tizen-libopener
+
#################################################
## tizen-database-devel
#################################################
install -m 0755 run-unittest.sh %{buildroot}%{_bindir}/tizen-unittests/tizen-database/
sed -i -e 's/<NAME>/tizen-database/g' %{buildroot}%{_bindir}/tizen-unittests/tizen-database/run-unittest.sh
+mkdir -p %{buildroot}%{_bindir}/tizen-unittests/tizen-libopener
+install -m 0755 run-unittest.sh %{buildroot}%{_bindir}/tizen-unittests/tizen-libopener/
+sed -i -e 's/<NAME>/tizen-libopener/g' %{buildroot}%{_bindir}/tizen-unittests/tizen-libopener/run-unittest.sh
+
mkdir -p %{buildroot}%{_bindir}/tizen-unittests/tizen-shared-queue
install -m 0755 run-unittest.sh %{buildroot}%{_bindir}/tizen-unittests/tizen-shared-queue/
sed -i -e 's/<NAME>/tizen-shared-queue/g' %{buildroot}%{_bindir}/tizen-unittests/tizen-shared-queue/run-unittest.sh
%{_bindir}/parcel_unittests
%{_bindir}/tizen-unittests/parcel/run-unittest.sh
+#################################################
+# tizen-libopener-devel
+#################################################
+%files -n tizen-libopener-devel
+%{_includedir}/tizen-libopener/*
+%{_libdir}/pkgconfig/tizen-libopener.pc
+
+%files -n tizen-libopener-unittests
+%{_bindir}/tizen-libopener_unittests
+%{_bindir}/tizen-unittests/tizen-libopener/run-unittest.sh
+
#################################################
# tizen-database-devel
#################################################
ADD_SUBDIRECTORY(parcel)
ADD_SUBDIRECTORY(tizen-database)
ADD_SUBDIRECTORY(tizen-shared-queue)
+ADD_SUBDIRECTORY(tizen-libopener)
--- /dev/null
+CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/tizen-libopener.pc.in
+ ${CMAKE_BINARY_DIR}/tizen-libopener.pc @ONLY)
+
+INSTALL(FILES ${CMAKE_BINARY_DIR}/tizen-libopener.pc
+ DESTINATION ${LIB_INSTALL_DIR}/pkgconfig/)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/libopener.hpp
+ DESTINATION include/tizen-libopener)
--- /dev/null
+/*
+ * Copyright (c) 2024 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed 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 TIZEN_LIBOPENER_HPP_
+#define TIZEN_LIBOPENER_HPP_
+
+#include <dlfcn.h>
+
+#include <string_view>
+#include <filesystem>
+
+namespace tizen_base {
+
+class LibOpener {
+ public:
+ LibOpener(std::string_view lib_path, int flag = RTLD_LAZY | RTLD_GLOBAL) {
+ handle_ = dlopen(lib_path.data(), flag);
+ if (handle_ == nullptr) {
+ throw std::filesystem::filesystem_error("dlopen() failed", std::error_code());
+ }
+ }
+
+ LibOpener() { handle_ = RTLD_DEFAULT; }
+
+ template <class T>
+ T TryBind(std::string_view symbol, T t = nullptr) {
+ T func_type = reinterpret_cast<T>(dlsym(handle_, symbol.data()));
+ if (func_type == nullptr) {
+ return nullptr;
+ }
+
+ return func_type;
+ }
+
+ template <class T>
+ T Bind(std::string_view symbol, T t = nullptr) {
+ T func_type = reinterpret_cast<T>(dlsym(handle_, symbol.data()));
+ if (func_type == nullptr) {
+ throw std::filesystem::filesystem_error(dlerror(), std::error_code());
+ return nullptr;
+ }
+
+ return func_type;
+ }
+
+ ~LibOpener() {
+ if (handle_ == RTLD_DEFAULT) return;
+ if (handle_) dlclose(handle_);
+ }
+
+ private:
+ void* handle_ = nullptr;
+};
+
+} // namespace tizen_base
+
+#endif // TIZEN_LIBOPENER_HPP_
--- /dev/null
+prefix=@PREFIX@
+includedir=${prefix}/include
+
+Name: tizen-libopener
+Description: C++ wrapper API for dlopen and dlsym
+Version: @VERSION@
+Requires:
+Cflags: -I${includedir} -I${includedir}/tizen-libopener
+cppflags: -I${includedir} -I${includedir}/tizen-libopener
ADD_SUBDIRECTORY(parcel_unittests)
ADD_SUBDIRECTORY(tizen-database_unittests)
ADD_SUBDIRECTORY(tizen-shared-queue_unittests)
+ADD_SUBDIRECTORY(tizen-libopener_unittests)
ADD_DEPENDENCIES(${TARGET_BUNDLE_UNITTESTS} ${TARGET_BUNDLE})
ADD_DEPENDENCIES(${TARGET_PARCEL_UNITTESTS} ${TARGET_PARCEL})
--- /dev/null
+ADD_DEFINITIONS("-DLIBDIR=\"${LIBDIR}\"")
+AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src TIZEN_LIBOPENER_UNITTESTS_SRCS)
+
+ADD_EXECUTABLE(${TARGET_TIZEN_LIBOPENER_UNITTESTS}
+ ${TIZEN_LIBOPENER_UNITTESTS_SRCS})
+
+TARGET_INCLUDE_DIRECTORIES(${TARGET_TIZEN_LIBOPENER_UNITTESTS} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/../
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../src
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../src/tizen-libopener
+)
+
+APPLY_PKG_CONFIG(${TARGET_TIZEN_LIBOPENER_UNITTESTS} PUBLIC
+ GMOCK_DEPS
+)
+
+TARGET_LINK_LIBRARIES(${TARGET_TIZEN_LIBOPENER_UNITTESTS} PRIVATE
+ "-ldl")
+
+INSTALL(TARGETS ${TARGET_TIZEN_LIBOPENER_UNITTESTS} DESTINATION bin)
--- /dev/null
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Licensed 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 <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <iostream>
+#include <vector>
+
+#include "tizen-libopener/libopener.hpp"
+
+namespace {} // namespace
+
+TEST(LibOpenerTest, Create_N) {
+ ASSERT_THROW(tizen_base::LibOpener opener("wrong_path/libglib-2.0.so.0"),
+ std::filesystem::filesystem_error);
+}
+
+TEST(LibOpenerTest, Bind) {
+ tizen_base::LibOpener opener(LIBDIR"/libglib-2.0.so.0");
+
+ using GMainContext = void;
+ using GMainLoop = void;
+ auto* g_main_loop_get_context =
+ opener.Bind<GMainContext* (*)(GMainLoop*)>("g_main_loop_get_context");
+ ASSERT_NE(g_main_loop_get_context, nullptr);
+}
+
+TEST(LibOpenerTest, Bind_N) {
+ tizen_base::LibOpener opener(LIBDIR"/libglib-2.0.so.0");
+
+ using GMainContext = void;
+ using GMainLoop = void;
+ ASSERT_THROW(opener.Bind<GMainContext* (*)(GMainLoop*)>("wrong_symbol"),
+ std::filesystem::filesystem_error);
+}
+
+TEST(LibOpenerTest, TryBind) {
+ tizen_base::LibOpener opener(LIBDIR"/libglib-2.0.so.0");
+
+ using GMainContext = void;
+ using GMainLoop = void;
+ auto* g_main_loop_get_context =
+ opener.TryBind<GMainContext* (*)(GMainLoop*)>("g_main_loop_get_context");
+ ASSERT_NE(g_main_loop_get_context, nullptr);
+}
--- /dev/null
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed 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 <gtest/gtest.h>
+#include <gmock/gmock.h>
+
+#include <exception>
+
+int main(int argc, char** argv) {
+ try {
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+ } catch (std::exception const &e) {
+ std::cout << "test_main caught exception: " << e.what() << std::endl;
+ return -1;
+ }
+}