Add libopener 85/319985/2
authorpjh9216 <jh9216.park@samsung.com>
Wed, 6 Nov 2024 04:52:00 +0000 (13:52 +0900)
committerpjh9216 <jh9216.park@samsung.com>
Wed, 6 Nov 2024 05:36:35 +0000 (14:36 +0900)
 - C++ wrapper API for dlopen and dlsym
 - example
  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");

Change-Id: Iaea4e2beb05856e4870824f149c5515335a334cc
Signed-off-by: pjh9216 <jh9216.park@samsung.com>
CMakeLists.txt
packaging/bundle.spec
src/CMakeLists.txt
src/tizen-libopener/CMakeLists.txt [new file with mode: 0644]
src/tizen-libopener/libopener.hpp [new file with mode: 0644]
src/tizen-libopener/tizen-libopener.pc.in [new file with mode: 0644]
tests/CMakeLists.txt
tests/tizen-libopener_unittests/CMakeLists.txt [new file with mode: 0644]
tests/tizen-libopener_unittests/src/test_libopener.cc [new file with mode: 0644]
tests/tizen-libopener_unittests/src/test_main.cc [new file with mode: 0644]

index aaea2db51e61c903702f30868627aa0eb959921c..fb8dc72341aa8f14861107d71bbef9396d3f5fd8 100644 (file)
@@ -4,6 +4,7 @@ PROJECT(bundle)
 
 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")
@@ -31,6 +32,7 @@ SET(TARGET_BUNDLE_UNITTESTS "bundle_unittests")
 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)
@@ -61,3 +63,7 @@ ADD_TEST(NAME ${TARGET_TIZEN_DATABASE_UNITTESTS}
 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)
index 75a6e027efa27b9d951f8f11901e7244b3503192..8ad10b4e59453ff7ee4adcb3045f019f16dc8909 100644 (file)
@@ -87,6 +87,26 @@ Group:      Development/Libraries
 %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
 #################################################
@@ -280,6 +300,10 @@ mkdir -p %{buildroot}%{_bindir}/tizen-unittests/tizen-database
 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
@@ -367,6 +391,17 @@ ln -sf %{_rust_dylibdir}/libtizen_parcel.so %{buildroot}%{_libdir}/libtizen_parc
 %{_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
 #################################################
index 9373d860fd5631a69d0503a2d28066d7e4381ad0..713e9b5625582d081b6b074d1075adf339c4733c 100644 (file)
@@ -2,3 +2,4 @@ ADD_SUBDIRECTORY(bundle)
 ADD_SUBDIRECTORY(parcel)
 ADD_SUBDIRECTORY(tizen-database)
 ADD_SUBDIRECTORY(tizen-shared-queue)
+ADD_SUBDIRECTORY(tizen-libopener)
diff --git a/src/tizen-libopener/CMakeLists.txt b/src/tizen-libopener/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2d9bae9
--- /dev/null
@@ -0,0 +1,7 @@
+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)
diff --git a/src/tizen-libopener/libopener.hpp b/src/tizen-libopener/libopener.hpp
new file mode 100644 (file)
index 0000000..bf75704
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * 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_
diff --git a/src/tizen-libopener/tizen-libopener.pc.in b/src/tizen-libopener/tizen-libopener.pc.in
new file mode 100644 (file)
index 0000000..5f4aa3b
--- /dev/null
@@ -0,0 +1,9 @@
+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
index 30e9d3ef12c74d13e1848400f0353d91900d8866..b554db1ae81d152e5f83897a4735ce39d3a4ffa9 100644 (file)
@@ -2,6 +2,7 @@ ADD_SUBDIRECTORY(bundle_unittests)
 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})
diff --git a/tests/tizen-libopener_unittests/CMakeLists.txt b/tests/tizen-libopener_unittests/CMakeLists.txt
new file mode 100644 (file)
index 0000000..1e9b350
--- /dev/null
@@ -0,0 +1,22 @@
+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)
diff --git a/tests/tizen-libopener_unittests/src/test_libopener.cc b/tests/tizen-libopener_unittests/src/test_libopener.cc
new file mode 100644 (file)
index 0000000..b043439
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * 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);
+}
diff --git a/tests/tizen-libopener_unittests/src/test_main.cc b/tests/tizen-libopener_unittests/src/test_main.cc
new file mode 100644 (file)
index 0000000..da13aab
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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;
+  }
+}