Skip to content

Commit

Permalink
examples: Add basic PythonPlugin example
Browse files Browse the repository at this point in the history
  • Loading branch information
taminob committed Mar 26, 2024
1 parent ccd9adc commit 44c579b
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 0 deletions.
1 change: 1 addition & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ add_subdirectory(configurable_plugin)
add_subdirectory(lua_plugin)
add_subdirectory(multi_language_plugin)
add_subdirectory(multi_return_lua_plugin)
add_subdirectory(python_plugin)
10 changes: 10 additions & 0 deletions examples/python_plugin/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
add_executable(python_plugin_manager python_plugin_manager.cpp)
target_link_libraries(python_plugin_manager PRIVATE ${LIBRARY_TARGET})

add_custom_command(
TARGET python_plugin_manager
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/plugin.py
$<TARGET_FILE_DIR:python_plugin_manager>/plugin_1.py
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/plugin.py
$<TARGET_FILE_DIR:python_plugin_manager>/plugin_2.py)
19 changes: 19 additions & 0 deletions examples/python_plugin/plugin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import time


def initialize(something):
print("initialize: ", something)


def loop(something):
# this only works because of the I/O and sleep;
# a loop without any "non-python" operations may block all threads
# wanting to execute python plugins;
# if python 3.12 or newer is used, multiple threads can execute
# python code at the same time
while True:
print("loop: ", something)
time.sleep(1)


print("loading")
63 changes: 63 additions & 0 deletions examples/python_plugin/python_plugin_manager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#include "plugin_manager.h"
#include "python/plugin.h"

#include <exception>
#include <filesystem>
#include <iostream>
#include <thread>
#include <tuple>
#include <utility>
#include <vector>

int main(int argc, char* argv[])
{
try {
if (argc < 1) {
return -1;
}
// path to plugins can be passed via command line;
// if no path was specified, the location of the executable is used instead
std::filesystem::path plugin_dir;
if (argc < 2) {
plugin_dir = std::filesystem::path { argv[0] }.parent_path();
} else {
plugin_dir = std::filesystem::path { argv[1] };
}
ppplugin::GenericPluginManager<ppplugin::PythonPlugin> manager;
std::vector<std::thread> threads;
int plugin_number {};

// recursively traverse filesystem to find scripts
const std::filesystem::recursive_directory_iterator dir_iterator { plugin_dir };
for (const auto& entry : dir_iterator) {
if (!entry.is_regular_file()) {
continue;
}
const auto& path = entry.path();
// only load files ending with ".py" and execute in separate thread
if (path.extension() == ".py") {
auto plugin = manager.loadPythonPlugin(path);
if (plugin) {
threads.emplace_back([plugin = std::move(*plugin), plugin_number = plugin_number++]() mutable {
// ignore calling errors
std::ignore = plugin.call<void>("initialize", plugin_number);
std::ignore = plugin.call<void>("loop", std::to_string(plugin_number));
});
} else {
std::cerr << "Failed to load " << path << '\n';
}
}
}

for (auto& thread : threads) {
thread.join();
}
} catch (const std::exception& exception) {
std::cerr << "A fatal error occurred: '" << exception.what() << "'\n";
return 1;
} catch (...) {
std::cerr << "An unknown fatal error occurred!";
return 1;
}
return 0;
}

0 comments on commit 44c579b

Please sign in to comment.