Added create_struct and create_union function to Python API
This commit is contained in:
parent
c6134bc038
commit
17096055f8
@ -16,6 +16,7 @@ namespace hex {
|
|||||||
SelectionChangeRequest,
|
SelectionChangeRequest,
|
||||||
|
|
||||||
AddBookmark,
|
AddBookmark,
|
||||||
|
AppendPatternLanguageCode,
|
||||||
|
|
||||||
ProjectFileStore,
|
ProjectFileStore,
|
||||||
ProjectFileLoad
|
ProjectFileLoad
|
||||||
|
@ -25,6 +25,9 @@ namespace hex {
|
|||||||
static PyObject* Py_getFilePath(PyObject *self, PyObject *args);
|
static PyObject* Py_getFilePath(PyObject *self, PyObject *args);
|
||||||
static PyObject* Py_addPatch(PyObject *self, PyObject *args);
|
static PyObject* Py_addPatch(PyObject *self, PyObject *args);
|
||||||
static PyObject* Py_addBookmark(PyObject *self, PyObject *args);
|
static PyObject* Py_addBookmark(PyObject *self, PyObject *args);
|
||||||
|
|
||||||
|
static PyObject* Py_addStruct(PyObject *self, PyObject *args);
|
||||||
|
static PyObject* Py_addUnion(PyObject *self, PyObject *args);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -6,9 +6,13 @@
|
|||||||
|
|
||||||
#define PY_SSIZE_T_CLEAN
|
#define PY_SSIZE_T_CLEAN
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
|
#include <structmember.h>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
|
using namespace std::literals::string_literals;
|
||||||
|
|
||||||
namespace hex {
|
namespace hex {
|
||||||
|
|
||||||
PyObject* LoaderScript::Py_getFilePath(PyObject *self, PyObject *args) {
|
PyObject* LoaderScript::Py_getFilePath(PyObject *self, PyObject *args) {
|
||||||
@ -64,16 +68,99 @@ namespace hex {
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject* createStructureType(std::string keyword, PyObject *args) {
|
||||||
|
auto type = PyTuple_GetItem(args, 0);
|
||||||
|
if (type == nullptr) {
|
||||||
|
PyErr_BadArgument();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto instance = PyObject_CallObject(type, nullptr);
|
||||||
|
if (instance == nullptr) {
|
||||||
|
PyErr_BadArgument();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
hex::ScopeExit instanceCleanup([&]{ Py_DECREF(instance); });
|
||||||
|
|
||||||
|
if (instance->ob_type->tp_base == nullptr || instance->ob_type->tp_base->tp_name != "ImHexType"s) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "class type must extend from ImHexType");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto dict = instance->ob_type->tp_dict;
|
||||||
|
if (dict == nullptr) {
|
||||||
|
PyErr_BadArgument();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto annotations = PyDict_GetItemString(dict, "__annotations__");
|
||||||
|
if (annotations == nullptr) {
|
||||||
|
PyErr_BadArgument();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto list = PyDict_Items(annotations);
|
||||||
|
if (list == nullptr) {
|
||||||
|
PyErr_BadArgument();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
hex::ScopeExit listCleanup([&]{ Py_DECREF(list); });
|
||||||
|
|
||||||
|
std::string code = keyword + " " + instance->ob_type->tp_name + " {\n";
|
||||||
|
|
||||||
|
for (u16 i = 0; i < PyList_Size(list); i++) {
|
||||||
|
auto item = PyList_GetItem(list, i);
|
||||||
|
|
||||||
|
auto memberName = PyUnicode_AsUTF8(PyTuple_GetItem(item, 0));
|
||||||
|
auto memberType = PyTuple_GetItem(item, 1);
|
||||||
|
if (memberType == nullptr) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "member needs to have a annotation extending from ImHexType");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
auto memberTypeInstance = PyObject_CallObject(memberType, nullptr);
|
||||||
|
if (memberTypeInstance == nullptr || memberTypeInstance->ob_type->tp_base == nullptr || memberTypeInstance->ob_type->tp_base->tp_name != "ImHexType"s) {
|
||||||
|
PyErr_SetString(PyExc_TypeError, "member needs to have a annotation extending from ImHexType");
|
||||||
|
Py_DECREF(memberTypeInstance);
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
code += " "s + memberTypeInstance->ob_type->tp_name + " "s + memberName + ";\n";
|
||||||
|
|
||||||
|
Py_DECREF(memberTypeInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
code += "};\n";
|
||||||
|
|
||||||
|
View::postEvent(Events::AppendPatternLanguageCode, code.c_str());
|
||||||
|
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* LoaderScript::Py_addStruct(PyObject *self, PyObject *args) {
|
||||||
|
return createStructureType("struct", args);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* LoaderScript::Py_addUnion(PyObject *self, PyObject *args) {
|
||||||
|
return createStructureType("union", args);
|
||||||
|
}
|
||||||
|
|
||||||
bool LoaderScript::processFile(std::string_view scriptPath) {
|
bool LoaderScript::processFile(std::string_view scriptPath) {
|
||||||
Py_SetProgramName(Py_DecodeLocale(__argv[0], nullptr));
|
Py_SetProgramName(Py_DecodeLocale(__argv[0], nullptr));
|
||||||
|
|
||||||
|
if (std::filesystem::exists(std::filesystem::path(__argv[0]).parent_path().string() + "/lib/python3.8"))
|
||||||
Py_SetPythonHome(Py_DecodeLocale(std::filesystem::path(__argv[0]).parent_path().string().c_str(), nullptr));
|
Py_SetPythonHome(Py_DecodeLocale(std::filesystem::path(__argv[0]).parent_path().string().c_str(), nullptr));
|
||||||
|
|
||||||
PyImport_AppendInittab("imhex", []() -> PyObject* {
|
PyImport_AppendInittab("_imhex", []() -> PyObject* {
|
||||||
|
|
||||||
static PyMethodDef ImHexMethods[] = {
|
static PyMethodDef ImHexMethods[] = {
|
||||||
{ "get_file_path", &LoaderScript::Py_getFilePath, METH_NOARGS, "Returns the path of the file being loaded." },
|
{ "get_file_path", &LoaderScript::Py_getFilePath, METH_NOARGS, "Returns the path of the file being loaded." },
|
||||||
{ "patch", &LoaderScript::Py_addPatch, METH_VARARGS, "Patches a region of memory" },
|
{ "patch", &LoaderScript::Py_addPatch, METH_VARARGS, "Patches a region of memory" },
|
||||||
{ "add_bookmark", &LoaderScript::Py_addBookmark, METH_VARARGS, "Adds a bookmark" },
|
{ "add_bookmark", &LoaderScript::Py_addBookmark, METH_VARARGS, "Adds a bookmark" },
|
||||||
|
{ "add_struct", &LoaderScript::Py_addStruct, METH_VARARGS, "Adds a struct" },
|
||||||
|
{ "add_union", &LoaderScript::Py_addUnion, METH_VARARGS, "Adds a union" },
|
||||||
{ nullptr, nullptr, 0, nullptr }
|
{ nullptr, nullptr, 0, nullptr }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -81,11 +168,22 @@ namespace hex {
|
|||||||
PyModuleDef_HEAD_INIT, "imhex", nullptr, -1, ImHexMethods, nullptr, nullptr, nullptr, nullptr
|
PyModuleDef_HEAD_INIT, "imhex", nullptr, -1, ImHexMethods, nullptr, nullptr, nullptr, nullptr
|
||||||
};
|
};
|
||||||
|
|
||||||
return PyModule_Create(&ImHexModule);
|
auto module = PyModule_Create(&ImHexModule);
|
||||||
|
if (module == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return module;
|
||||||
});
|
});
|
||||||
|
|
||||||
Py_Initialize();
|
Py_Initialize();
|
||||||
|
|
||||||
|
{
|
||||||
|
auto sysPath = PySys_GetObject("path");
|
||||||
|
auto path = PyUnicode_FromString("lib");
|
||||||
|
|
||||||
|
PyList_Insert(sysPath, 0, path);
|
||||||
|
}
|
||||||
|
|
||||||
FILE *scriptFile = fopen(scriptPath.data(), "r");
|
FILE *scriptFile = fopen(scriptPath.data(), "r");
|
||||||
PyRun_SimpleFile(scriptFile, scriptPath.data());
|
PyRun_SimpleFile(scriptFile, scriptPath.data());
|
||||||
|
|
||||||
|
@ -87,6 +87,13 @@ namespace hex {
|
|||||||
this->parsePattern(this->m_textEditor.GetText().data());
|
this->parsePattern(this->m_textEditor.GetText().data());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
View::subscribeEvent(Events::AppendPatternLanguageCode, [this](const void *userData) {
|
||||||
|
const char *code = static_cast<const char*>(userData);
|
||||||
|
|
||||||
|
this->m_textEditor.InsertText("\n");
|
||||||
|
this->m_textEditor.InsertText(code);
|
||||||
|
});
|
||||||
|
|
||||||
View::subscribeEvent(Events::FileLoaded, [this](const void* userData) {
|
View::subscribeEvent(Events::FileLoaded, [this](const void* userData) {
|
||||||
if (!this->m_textEditor.GetText().empty())
|
if (!this->m_textEditor.GetText().empty())
|
||||||
return;
|
return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user