Skip to content

Commit

Permalink
sync commit - 2024/03/28
Browse files Browse the repository at this point in the history
  • Loading branch information
taminob committed Mar 27, 2024
1 parent 74e7d6e commit 0c2c97c
Show file tree
Hide file tree
Showing 15 changed files with 128 additions and 11 deletions.
11 changes: 11 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -1 +1,12 @@
BasedOnStyle: WebKit
QualifierAlignment: 'Custom'
QualifierOrder: [
'friend',
'static',
'constexpr',
'inline',
'volatile',
'restrict',
'const',
'type',
]
3 changes: 1 addition & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ option(PPPLUGIN_ENABLE_UNREACHABLE_SANITIZE
"Enable compilation with unreachable sanitize flags" OFF)

find_package(Boost 1.61.0 REQUIRED COMPONENTS headers filesystem)
find_package(Python 3.0 REQUIRED COMPONENTS Development)
find_package(Python 3.9...<3.12 REQUIRED COMPONENTS Development)
find_package(Lua 5.2 REQUIRED)

set(THREADS_PREFER_PTHREAD_FLAG ON)
Expand Down Expand Up @@ -60,7 +60,6 @@ set(DEBUG_FLAGS "-g3")
if(${PPPLUGIN_ENABLE_CPP17_COMPATIBILITY})
find_package(fmt 8.1.0 REQUIRED)
set(CMAKE_CXX_STANDARD 17)
# TODO: generate C++17 compatible header files instead
add_definitions("-DPPPLUGIN_CPP17_COMPATIBILITY")
else()
set(CMAKE_CXX_STANDARD 20)
Expand Down
2 changes: 2 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ add_subdirectory(lua_plugin)
add_subdirectory(multi_language_plugin)
add_subdirectory(multi_return_lua_plugin)
add_subdirectory(python_plugin)

add_subdirectory(testing) # TODO: to be removed
4 changes: 3 additions & 1 deletion examples/lua_plugin/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ add_custom_command(
TARGET lua_plugin_manager
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/plugin.lua
$<TARGET_FILE_DIR:lua_plugin_manager>)
$<TARGET_FILE_DIR:lua_plugin_manager>/plugin_1.lua
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/plugin.lua
$<TARGET_FILE_DIR:lua_plugin_manager>/plugin_2.lua)
6 changes: 4 additions & 2 deletions examples/lua_plugin/lua_plugin_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,11 @@ int main(int argc, char* argv[])
// only load files ending with ".lua" and execute in separate thread
if (path.extension() == ".lua") {
if (auto plugin = manager.loadLuaPlugin(path)) {
threads.emplace_back([plugin = std::move(*plugin)]() mutable {
threads.emplace_back([plugin = std::move(*plugin), plugin_number = threads.size()]() mutable {
// data race due to shared resource "stdout",
// but Lua plugins are otherwise thread-safe
std::ignore = plugin.call<void>("initialize");
std::ignore = plugin.call<void>("loop", "2");
std::ignore = plugin.call<void>("loop", plugin_number);
});
}
}
Expand Down
2 changes: 1 addition & 1 deletion examples/python_plugin/python_plugin_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ int main(int argc, char* argv[])
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);
plugin.call<void>("initialize", plugin_number).valueOrElse([](ppplugin::CallError error) { std::cerr << error.what() << std::endl; });
std::ignore = plugin.call<void>("loop", std::to_string(plugin_number));
});
} else {
Expand Down
10 changes: 10 additions & 0 deletions examples/testing/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
add_executable(testing testing.cpp)
target_link_libraries(testing ${LIBRARY_TARGET})

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


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


def loop(something):
while True:
print("loop: ", something)
time.sleep(1)


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

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

int main(int argc, char* argv[])
{
std::vector<std::thread> threads;
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> const manager;
int plugin_number {};
std::vector<ppplugin::PythonPlugin> const plugins;

// checkout: https://stackoverflow.com/questions/26061298/python-multi-thread-multi-interpreter-c-api#26570708
// 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 ".lua" and execute in separate thread
if (path.extension() == ".py") {
ppplugin::PythonInterpreter interpreter;
if (auto error = interpreter.load(path.string())) {
std::cerr << "failed to load " << path << '\n';
// return -1;
}
threads.emplace_back([manager, path, plugin_number = plugin_number++, interpreter = std::move(interpreter)]() mutable {
interpreter.call<void>("initialize", std::hash<std::thread::id> {}(std::this_thread::get_id()));
interpreter.call<void>("loop", std::hash<std::thread::id> {}(std::this_thread::get_id()));
});
}
}
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;
}
2 changes: 1 addition & 1 deletion include/errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class CallError {
{
}

[[nodiscard]] CallError error() const { return error_; }
[[nodiscard]] CallError::Code error() const { return error_; }
[[nodiscard]] const std::string& what() const { return what_; }
#ifndef PPPLUGIN_CPP17_COMPATIBILITY
[[nodiscard]] const std::source_location& location() const
Expand Down
8 changes: 6 additions & 2 deletions include/lua/lua_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,12 @@ class LuaState {
std::optional<std::function<Func>> popFunction(bool always_pop = false);

void pushOne(double value);
void pushOne(int value);
void pushOne(unsigned int value) { pushOne(static_cast<long long>(value)); }
void pushOne(int value) { pushOne(static_cast<long long>(value)); }
void pushOne(unsigned long value) { pushOne(static_cast<long long>(value)); }
void pushOne(long value) { pushOne(static_cast<long long>(value)); }
void pushOne(unsigned long long value) { pushOne(static_cast<long long>(value)); }
void pushOne(long long value);
void pushOne(const char* value);
void pushOne(std::string_view value);
void pushOne(bool value);
Expand Down Expand Up @@ -259,7 +264,6 @@ auto LuaState::topFunction()
}
return std::optional<decltype(top_function)> { std::nullopt };
}

} // namespace ppplugin

#endif // PPPLUGIN_LUA_STATE_H
3 changes: 3 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ target_link_libraries(
PUBLIC Python::Python
PRIVATE ${LUA_LIBRARIES})
if(${PPPLUGIN_ENABLE_CPP17_COMPATIBILITY})
# TODO: generate C++17 compatible header files instead
# target_compile_options(${LIBRARY_TARGET} PUBLIC
# "-DPPPLUGIN_CPP17_COMPATIBILITY") # TODO: fix
target_link_libraries(${LIBRARY_TARGET} PUBLIC fmt::fmt)
endif()
target_include_directories(
Expand Down
5 changes: 5 additions & 0 deletions src/boost_dll_loader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
#include <boost/filesystem/path.hpp>

namespace {
/**
* Helper function to determine if given function can be called in given library.
*
* @return std::nullopt if function is callable, otherwise an error
*/
std::optional<ppplugin::CallError> isCallable(const boost::dll::shared_library& library, const std::string& function_name)
{
if (!library.is_loaded()) {
Expand Down
3 changes: 2 additions & 1 deletion src/lua_script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ LuaScript::LuaScript()
luaL_openlibs(state_.state());
state_.registerPanicHandler([](lua_State* state) -> int {
auto error = LuaState::wrap(state).top<std::string>();
// TODO: don't throw because will cross library boundaries
// TODO: don't throw because will cross library boundaries;
// use global error state (thread-local or lock-protected)
throw std::runtime_error(format("Lua PANIC: '{}'!", error.value_or("?")));
});
// TODO: setup lua_setwarnf
Expand Down
2 changes: 1 addition & 1 deletion src/lua_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ void LuaState::pushOne(double value)
lua_pushnumber(state(), value);
}

void LuaState::pushOne(int value)
void LuaState::pushOne(long long value)
{
lua_pushinteger(state(), value);
}
Expand Down

0 comments on commit 0c2c97c

Please sign in to comment.