/* This file is part of MAUS: http://micewww.pp.rl.ac.uk/projects/maus * * MAUS is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * MAUS is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MAUS. If not, see . */ #ifndef _SRC_COMMON_CPP_API_WRAPMAPBASE_ #define _SRC_COMMON_CPP_API_WRAPMAPBASE_ #include #include #include "src/common_cpp/Utils/JsonWrapper.hh" #include "src/common_cpp/DataStructure/Data.hh" namespace MAUS { static PyObject *InvalidModuleError; static PyObject *InvalidInputError; static PyObject *InvalidOutputError; static std::string ModuleClassName; template class WrapMapBase { public: /// Create a new instance of the MODULE parameter static PyObject* ModuleNew(PyObject *self, PyObject *args) { if (!PyArg_ParseTuple(args, (std::string(":ModuleNew_")+ ModuleClassName).c_str())) { return NULL; } MODULE* module = new MODULE(); void* vptr = static_cast(module); PyObject *resultobj = PyCapsule_New(vptr, "Module", NULL); return resultobj; } /// Delete the MODULE object owned by the wrapper class static PyObject* ModuleDelete(PyObject *self, PyObject *args) { PyObject* obj0 = NULL; if (!PyArg_ParseTuple(args, (std::string("O:ModuleDelete_")+ ModuleClassName).c_str(), &obj0)) { return NULL; } if (!PyCapsule_IsValid(obj0, "Module")) { std::string error; error = "First input PyCapsule must contain the pointer"; error += " to the Module"; PyErr_SetString(InvalidModuleError, error.c_str()); return NULL; } void* vptr = PyCapsule_GetPointer(obj0, "Module"); MODULE* module = static_cast(vptr); delete module; Py_RETURN_NONE; } /// Run the MODULE object's birth function. static PyObject* ModuleBirth(PyObject *self, PyObject *args) { PyObject* obj0 = NULL; char* birth_arg = NULL; if (!PyArg_ParseTuple(args, (std::string("Os:ModuleBirth_")+ ModuleClassName).c_str(), &obj0, &birth_arg)) { return NULL; } if (!PyCapsule_IsValid(obj0, "Module")) { std::string error; error = "First input PyCapsule must contain the pointer"; error += " to the Module"; PyErr_SetString(InvalidModuleError, error.c_str()); return NULL; } void* vptr = PyCapsule_GetPointer(obj0, "Module"); MODULE* module = static_cast(vptr); std::string argJsonConfigDocument(birth_arg); module->birth(argJsonConfigDocument); Py_RETURN_NONE; } /// Run the MODULE object's death function. static PyObject* ModuleDeath(PyObject *self, PyObject *args) { PyObject* obj0 = NULL; if (!PyArg_ParseTuple(args, (std::string("O:ModuleDeath_")+ ModuleClassName).c_str(), &obj0)) { return NULL; } if (!PyCapsule_IsValid(obj0, "Module")) { std::string error; error = "First input PyCapsule must contain the pointer"; error += " to the Module"; PyErr_SetString(InvalidModuleError, error.c_str()); return NULL; } void* vptr = PyCapsule_GetPointer(obj0, "Module"); MODULE* module = static_cast(vptr); module->death(); Py_RETURN_NONE; } /// Set the MODULE object's input format. static PyObject* ModuleSetInput(PyObject *self, PyObject *args) { PyObject* obj0 = NULL; const char *input_char = NULL; // Interpret the input as a PyObject* and a string, otherwise fail. if (!PyArg_ParseTuple(args, (std::string("Os:ModuleSetInput")+ ModuleClassName).c_str(), &obj0, &input_char)) { std::string error; error = "Input parameters must be 'Module'"; error +=" + 'string', where string defines the input type."; PyErr_SetString(InvalidInputError, error.c_str()); return NULL; } // Check the PyObject* is a MODULE* if (!PyCapsule_IsValid(obj0, "Module")) { std::string error; error = "First input PyCapsule must contain the pointer"; error += " to the Module"; PyErr_SetString(InvalidModuleError, error.c_str()); return NULL; } // Get the module void* vptr0 = PyCapsule_GetPointer(obj0, "Module"); MODULE* module = static_cast(vptr0); // Check the MODULE* is valid if (!module) { std::string error; error = "First input Module is invalid pointer"; PyErr_SetString(InvalidModuleError, error.c_str()); return NULL; } module->set_input(input_char); Py_RETURN_NONE; } /// Get the MODULE object's output format. static PyObject* ModuleGetOutput(PyObject *self, PyObject *args) { PyObject* obj0 = NULL; // Interpret the input as a PyObject*, otherwise fail. if (!PyArg_ParseTuple(args, (std::string("O:ModuleGetOutput")+ ModuleClassName).c_str(), &obj0)) { std::string error; error = "Input parameters must be 'Module'"; PyErr_SetString(InvalidInputError, error.c_str()); return NULL; } // Check the PyObject* is a MODULE*, if (!PyCapsule_IsValid(obj0, "Module")) { std::string error; error = "First input PyCapsule must contain the pointer"; error += " to the Module"; PyErr_SetString(InvalidModuleError, error.c_str()); return NULL; } // Get the module void* vptr0 = PyCapsule_GetPointer(obj0, "Module"); MODULE* module = static_cast(vptr0); // Check the MODULE* is valid if (!module) { std::string error; error = "First input Module is invalid pointer"; PyErr_SetString(InvalidModuleError, error.c_str()); return NULL; } std::string temp = module->get_output(); return PyString_FromString(temp.c_str()); } /// Run the MODULE object's process function. static PyObject* ModuleProcess(PyObject *self, PyObject *args) { // Parse two elements, the module and the data object PyObject* obj0 = NULL; PyObject* obj1 = NULL; std::string format = "OO:ModuleProcess"; format += ModuleClassName; if (!PyArg_ParseTuple(args, format.c_str(), &obj0, &obj1)) { std::string error; error = "Unable to interpret inputs as two PyObject pointers"; PyErr_SetString(InvalidInputError, error.c_str()); return NULL; } // First object is going to be the module if (!PyCapsule_IsValid(obj0, "Module")) { std::string error; error = "First input PyCapsule must contain the pointer"; error += " to the Module"; PyErr_SetString(InvalidModuleError, error.c_str()); return NULL; } void* vptr0 = PyCapsule_GetPointer(obj0, "Module"); MODULE* module = static_cast(vptr0); // input_type can be either: std::string, MAUS::Data* or Json::Value*. std::string input_type = module->get_input(); if (input_type.compare("std::string") == 0) { // std::string input if (!PyString_Check(obj1)) { std::string error; error = "Expected std::string, data of wrong type"; PyErr_SetString(InvalidInputError, error.c_str()); return NULL; } std::string event_string(PyString_AsString(obj1)); // Convert the string to a Json::Value Json::Value imported_json = JsonWrapper::StringToJson(event_string); PyObject *resultobj = module->process_pyobj(&imported_json); return resultobj; } if (input_type.compare("Json::Value") == 0) { // Json::Value* input if (!PyCapsule_IsValid(obj1, "Json::Value")) { std::string error; error = "Expected Json::Value pointer, data of wrong type"; PyErr_SetString(InvalidInputError, error.c_str()); return NULL; } void* vptr1 = PyCapsule_GetPointer(obj1, "Json::Value"); Json::Value* input_json = static_cast(vptr1); PyObject *resultobj = module->process_pyobj(input_json); return resultobj; } if (input_type.compare("MAUS::Data") == 0) { // MAUS::Data* input if (!PyCapsule_IsValid(obj1, "MAUS::Data")) { std::string error; error = "Expected MAUS::Data pointer, data of wrong type"; PyErr_SetString(InvalidInputError, error.c_str()); return NULL; } void* vptr1 = PyCapsule_GetPointer(obj1, "MAUS::Data"); MAUS::Data* input_data = static_cast(vptr1); PyObject *resultobj = module->process_pyobj(input_data); return resultobj; } std::string error; error = "Second input PyCapsule must contain; 'std::string',"; error += " 'Json::Value' or 'MAUS::Data'"; PyErr_SetString(InvalidInputError, error.c_str()); return NULL; } }; } // ~MAUS #endif