ADD_VIST_COMMON_LIBRARY(vist_common archive.cpp
common.cpp
+ dynamic-loader.cpp
stringfy.cpp
thread-pool.cpp)
+SET(TARGET "test-plugin")
+ADD_LIBRARY(${TARGET} SHARED tests/res/sample-plugin.cpp)
+TARGET_LINK_LIBRARIES(${TARGET} vist-common)
+
+INSTALL(TARGETS ${TARGET} DESTINATION ${PLUGIN_INSTALL_DIR})
+
FILE(GLOB COMMON_TESTS "tests/*.cpp")
ADD_VIST_TEST(${COMMON_TESTS})
--- /dev/null
+/*
+ * Copyright (c) 2020-present 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 <vist/dynamic-loader.hpp>
+
+namespace vist {
+
+DynamicLoader::DynamicLoader(const std::string& path, int flag)
+ : scopedHandle(init(path, flag))
+{
+}
+
+DynamicLoader::ScopedHandle DynamicLoader::init(const std::string& path, int flag)
+{
+ auto open = [&]() -> void* {
+ ::dlerror();
+
+ auto handle = ::dlopen(path.c_str(), flag);
+ if (handle == nullptr) {
+ if (auto error = ::dlerror(); error != nullptr)
+ ERROR(VIST) << "Failed to open library: " << error;
+
+ THROW(ErrCode::RuntimeError) << "Failed to open library: " << path;
+ }
+
+ return handle;
+ };
+
+ auto close = [&](void* handle) {
+ ::dlerror();
+
+ if (::dlclose(handle) != 0)
+ THROW(ErrCode::RuntimeError) << "Failed to close library: " << ::dlerror();
+ };
+
+ return ScopedHandle(open(), close);
+}
+
+} // namespace vist
--- /dev/null
+# Copyright (c) 2019 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.
+#
+SET(TARGET "vist-plugin-sample")
+
+INCLUDE_DIRECTORIES(SYSTEM)
+
+ADD_LIBRARY(${TARGET} SHARED sample.cpp)
+SET_TARGET_PROPERTIES(${TARGET} PROPERTIES COMPILE_FLAGS "-fvisibility=default")
+TARGET_LINK_LIBRARIES(${TARGET} vist-common)
+
+IF(DEFINED GBS_BUILD)
+ INSTALL(FILES libvist-plugin-sample.so
+ RENAME sample
+ DESTINATION ${PLUGIN_INSTALL_DIR})
+ELSE(DEFINED GBS_BUILD)
+ INSTALL(TARGETS ${TARGET}
+ RENAME sample
+ DESTINATION ${PLUGIN_INSTALL_DIR})
+ENDIF(DEFINED GBS_BUILD)
--- /dev/null
+/*
+ * Copyright (c) 2020-present 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 <vist/dynamic-loader.hpp>
+
+#include "res/sample-plugin.hpp"
+
+#include <string>
+
+using namespace vist;
+
+TEST(DynamicLoaderTests, load)
+{
+ std::string path = std::string(PLUGIN_INSTALL_DIR) + "/libtest-plugin.so";
+ DynamicLoader loader(path);
+
+ auto factory = loader.load<SamplePlugin::FactoryType>("SampleFactory");
+ EXPECT_NE(factory, nullptr);
+
+ auto samplePlugin = (*factory)();
+ EXPECT_NE(samplePlugin, nullptr);
+
+ EXPECT_EQ(samplePlugin->test(), "sample-plugin-test");
+}
+
+TEST(DynamicLoaderTests, not_exist_path)
+{
+ try {
+ DynamicLoader loader("not_exists");
+ EXPECT_TRUE(false);
+ } catch (const std::exception&) {
+ EXPECT_TRUE(true);
+ }
+}
+
+TEST(DynamicLoaderTests, not_exist_symbol)
+{
+ try {
+ std::string path = std::string(PLUGIN_INSTALL_DIR) + "/libtest-plugin.so";
+ DynamicLoader loader(path);
+
+ loader.load<SamplePlugin::FactoryType>("not_exists");
+ EXPECT_TRUE(false);
+ } catch (const std::exception&) {
+ EXPECT_TRUE(true);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2020-present 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 "sample-plugin.hpp"
+
+extern "C" SamplePlugin* SampleFactory()
+{
+ return new SamplePlugin;
+}
--- /dev/null
+/*
+ * Copyright (c) 2020-present 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 <string>
+
+struct SamplePlugin {
+ using FactoryType = SamplePlugin * (*)();
+
+ std::string test()
+ {
+ return "sample-plugin-test";
+ }
+};
--- /dev/null
+/*
+ * Copyright (c) 2020-present 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
+ */
+
+#pragma once
+
+#include <vist/exception.hpp>
+#include <vist/logger.hpp>
+
+#include <functional>
+#include <memory>
+#include <string>
+
+#include <dlfcn.h>
+
+namespace vist {
+
+class DynamicLoader final {
+public:
+ explicit DynamicLoader(const std::string& path, int flag = RTLD_LAZY);
+
+ template<typename Symbol>
+ Symbol load(const std::string& name);
+
+private:
+ using ScopedHandle = std::unique_ptr<void, std::function<void(void*)>>;
+ ScopedHandle init(const std::string& path, int flag);
+
+ ScopedHandle scopedHandle;
+};
+
+template<typename T>
+T DynamicLoader::load(const std::string& name)
+{
+ ::dlerror();
+
+ auto symbol = ::dlsym(this->scopedHandle.get(), name.c_str());
+ if (symbol == nullptr) {
+ if (auto error = ::dlerror(); error != nullptr)
+ ERROR(VIST) << "Failed to load symbol: " << error;
+
+ THROW(ErrCode::RuntimeError) << "Failed to load symbol: " << name;
+ }
+
+ return reinterpret_cast<T>(symbol);
+}
+
+} // namespace vist