mana: add a python plugin

This commit is contained in:
Florian Lüke 2024-12-26 03:08:26 +01:00
parent 6f7102549e
commit 13c73cfdfc
4 changed files with 133 additions and 1 deletions

View file

@ -20,7 +20,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
option(MNODE_BUILD_TESTS "Build mnode test binaries" ${MESYTEC_MNODE_MAIN_PROJECT})
if (MNODE_BUILD_TESTS)
find_package(GTest CONFIG)
find_package(GTest CONFIG QUIET)
if (NOT GTest_FOUND)
include(FetchContent)
FetchContent_Declare(googletest URL https://github.com/google/googletest/archive/refs/tags/v1.15.2.zip)
@ -34,6 +34,14 @@ if (MNODE_BUILD_TESTS)
enable_testing()
endif()
include(FetchContent)
FetchContent_Declare(pybind11 GIT_REPOSITORY https://github.com/pybind/pybind11 GIT_TAG v2.13.6)
FetchContent_GetProperties(pybind11)
if(NOT pybind11_POPULATED)
FetchContent_Populate(pybind11)
add_subdirectory(${pybind11_SOURCE_DIR} ${pybind11_BINARY_DIR})
endif()
include(CMakeRC)
cmrc_add_resource_library(mnode-resources
ALIAS mnode::resources NAMESPACE mnode::resources

View file

@ -38,3 +38,9 @@ if (ROOT_FOUND)
add_library(mana-plugin-root-histogram SHARED mana_plugin_root_histogram.cc)
target_link_libraries(mana-plugin-root-histogram PRIVATE mana mesytec-mnode rxi-logc ${ROOT_LIBRARIES})
endif()
if (pybind11_FOUND)
add_library(mana-plugin-python SHARED mana_plugin_python.cc)
target_link_libraries(mana-plugin-python PRIVATE mana mesytec-mnode rxi-logc pybind11::embed)
file(CREATE_LINK ${CMAKE_CURRENT_SOURCE_DIR}/mana_python_test_plugin.py ${CMAKE_BINARY_DIR}/mana_python_test_plugin.py COPY_ON_ERROR SYMBOLIC)
endif()

105
src/mana_plugin_python.cc Normal file
View file

@ -0,0 +1,105 @@
#include "internal/mana_lib.hpp"
#include <mesytec-mvlc/cpp_compat.h>
extern "C"
{
#include "internal/rxi/log.h"
}
#include <pybind11/embed.h>
#include <pybind11/stl.h>
using namespace mesytec;
using namespace mesytec::mnode;
namespace py = pybind11;
PYBIND11_EMBEDDED_MODULE(py_mana, m) {}
struct Context
{
py::scoped_interpreter interp;
py::module usercode;
py::object userobject;
py::object py_begin_run;
py::object py_event_data;
py::object py_end_run;
std::vector<std::vector<py::object>> eventBuffers;
};
MANA_DEFINE_PLUGIN_INIT(init)
{
log_set_level(LOG_DEBUG);
static Context g_ctx;
auto ctx = &g_ctx;
log_debug("init: ctx=%p", ctx);
// TODO: pass args to init()
// TODO: catch exceptions
ctx->usercode = py::module::import("mana_python_test_plugin");
return ctx;
}
MANA_DEFINE_PLUGIN_SHUTDOWN(shutdown)
{
(void)context;
log_debug("shutdown");
}
MANA_DEFINE_PLUGIN_BEGIN_RUN(begin_run)
{
log_debug("begin_run: context=%p, descriptor_json=%s", context, descriptor_json);
auto jRun = nlohmann::json::parse(descriptor_json);
auto ctx = reinterpret_cast<Context *>(context);
ctx->usercode.reload();
// TODO: check if the retrieved attributes are callable
ctx->py_begin_run = ctx->usercode.attr("begin_run");
ctx->py_event_data = ctx->usercode.attr("event_data");
ctx->py_end_run = ctx->usercode.attr("end_run");
ctx->py_begin_run(descriptor_json);
ctx->eventBuffers.clear();
ctx->eventBuffers.resize(jRun["events"].size());
for (size_t ei = 0; ei < jRun["events"].size(); ++ei)
{
auto &jEvent = jRun["events"][ei];
ctx->eventBuffers[ei].resize(jEvent["outputs"].size());
}
}
MANA_DEFINE_PLUGIN_END_RUN(end_run)
{
log_debug("end: context=%p, descriptor_json=%s", context, descriptor_json);
auto ctx = reinterpret_cast<Context *>(context);
ctx->py_end_run(descriptor_json);
}
MANA_DEFINE_PLUGIN_EVENT_DATA(process_event)
{
log_trace("event: ctx=%p, eventIndex=%d, arrayCount=%zu, totalBytes=%zu", context, eventIndex,
arrayCount, totalBytes);
auto ctx = reinterpret_cast<Context *>(context);
auto &buffers = ctx->eventBuffers.at(eventIndex);
assert(buffers.size() == arrayCount);
for (size_t ai = 0; ai < arrayCount; ++ai)
{
auto arraySpan = mana::get_span<float>(arrays[ai]);
ctx->eventBuffers[eventIndex][ai] =
py::memoryview::from_memory(arraySpan.data(), arraySpan.size() * sizeof(float));
}
ctx->py_event_data(eventIndex, ctx->eventBuffers);
}
MANA_DEFINE_PLUGIN_SYSTEM_EVENT(process_system_event)
{
log_trace("system_event: ctx=%p, size=%zu", context, size);
auto ctx = reinterpret_cast<Context *>(context);
}
extern "C" MANA_DEFINE_GET_PLUGIN(mana_get_plugin)
{
mana_plugin_t plugin;
plugin.init = init;
plugin.shutdown = shutdown;
plugin.begin_run = begin_run;
plugin.end_run = end_run;
plugin.process_event = process_event;
plugin.process_system_event = process_system_event;
return plugin;
}

View file

@ -0,0 +1,13 @@
import json
import py_mana
def begin_run(runDescription: str):
print("begin_run")
def end_run(runDescription: str):
print("end_run")
def event_data(eventIndex: int, dataArrays):
return
print(f"event[{eventIndex}]: {dataArrays}")