From 5267287b05990fc86e854a92c3945bdbfb940b2f Mon Sep 17 00:00:00 2001 From: John McCardle Date: Sun, 3 Sep 2023 12:46:23 -0400 Subject: [PATCH] checkpoint: found that py_instance causes segfaults when called separately, but the same exact code inside of the _getitem method works fine. I can't explain that. I guess I'll turn it into a macro so the actions are inline and I can move on to finishing the other UI classes. --- src/McRFPy_API.cpp | 20 +++++++-- src/UI.cpp | 88 ++++++++++++++++++++++++++++++++++----- src/UI.h | 101 +++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 187 insertions(+), 22 deletions(-) diff --git a/src/McRFPy_API.cpp b/src/McRFPy_API.cpp index a7e4fac..428e785 100644 --- a/src/McRFPy_API.cpp +++ b/src/McRFPy_API.cpp @@ -131,6 +131,8 @@ PyObject* PyInit_mcrfpy() Py_DECREF(&mcrfpydef::PyUIFrameType); return NULL; } + PyModule_AddType(m, &mcrfpydef::PyUICollectionType); + PyModule_AddType(m, &mcrfpydef::PyUICollectionIterType); return m; @@ -1124,11 +1126,21 @@ PyObject* McRFPy_API::_camFollow(PyObject* self, PyObject* args) { //McRFPy_API::_sceneUI PyObject* McRFPy_API::_sceneUI(PyObject* self, PyObject* args) { + using namespace mcrfpydef; const char *scene_cstr; if (!PyArg_ParseTuple(args, "s", &scene_cstr)) return NULL; - auto ui = Resources::game->scene_ui("uitest"); - if(ui) std::cout << "vector returned has size=" << ui->size() << std::endl; - Py_INCREF(Py_None); - return Py_None; + auto ui = Resources::game->scene_ui(scene_cstr); + if(!ui) + { + PyErr_SetString(PyExc_RuntimeError, "No scene found by that name"); + return NULL; + } + //std::cout << "vector returned has size=" << ui->size() << std::endl; + //Py_INCREF(Py_None); + //return Py_None; + PyUICollectionObject* o = (PyUICollectionObject*)PyUICollectionType.tp_alloc(&PyUICollectionType, 0); + if (o) + o->data = ui; + return (PyObject*)o; } diff --git a/src/UI.cpp b/src/UI.cpp index afd45fb..6ad2357 100644 --- a/src/UI.cpp +++ b/src/UI.cpp @@ -101,33 +101,101 @@ PyObjectsEnum UISprite::derived_type() return PyObjectsEnum::UISPRITE; } -PyObject* py_instance(std::shared_ptr source) +PyObject* mcrfpydef::py_instance(std::shared_ptr source) { // takes a UI drawable, calls its derived_type virtual function, and builds a Python object based on the return value. - using namespace mcrfpydef; - PyObject* newobj; + //using namespace mcrfpydef; + +PyTypeObject* colorType = &PyColorType; + PyObject* pyColor = colorType->tp_alloc(colorType, 0); + if (pyColor == NULL) + { + std::cout << "failure to allocate mcrfpy.Color / PyColorType" << std::endl; + return NULL; + } + PyColorObject* pyColorObj = reinterpret_cast(pyColor); + pyColorObj->data = std::make_shared(); + pyColorObj->data-> r = 255; + return (PyObject*)pyColorObj; + + + PyObject* newobj = NULL; + std::cout << "py_instance called\n"; switch (source->derived_type()) { case PyObjectsEnum::UIFRAME: + { + std::cout << "UIFRAME case\n" << std::flush; + PyTypeObject* UIFrameType = &PyUIFrameType; + //std::cout << "tp_alloc\n" << std::flush; + //PyObject* _o = UIFrameType->tp_alloc(UIFrameType, 0); + //std::cout << "reinterpret_cast\n" << std::flush; + //auto o = reinterpret_cast(_o); + //PyUIFrameObject* o = (PyUIFrameObject*)PyObject_New(PyUIFrameObject, UIFrameType); + + PyUIFrameObject* o = (PyUIFrameObject*)(UIFrameType->tp_alloc(UIFrameType, 0)); + //PyUIFrameObject* o = PyObject_New(PyUIFrameObject, UIFrameType); + + /* + // backtracking the problem: instantiate a PyColor of (255, 0, 0) for testing + PyTypeObject* colorType = &PyColorType; + PyObject* pyColor = colorType->tp_alloc(colorType, 0); + if (pyColor == NULL) { - PyUIFrameObject* o = (PyUIFrameObject*)PyUIFrameType.tp_alloc(&PyUIFrameType, 0); - if (o) - o->data = std::static_pointer_cast(source); - newobj = (PyObject*)o; - break; + std::cout << "failure to allocate mcrfpy.Color / PyColorType" << std::endl; + return NULL; } - /* not yet implemented + PyColorObject* pyColorObj = reinterpret_cast(pyColor); + pyColorObj->data = std::make_shared(); + pyColorObj->data-> r = 255; + return (PyObject*)pyColorObj; + */ + + + std::cout << "pointer check: " << o << "\n" << std::flush; + if (o) + { + std::cout << "Casting data...\n" << std::flush; + auto p = std::static_pointer_cast(source); + std::cout << "casted. Assigning...\n" << std::flush; + //o->data = std::make_shared(); + + o->data = p; + //std::cout << "assigned.\n" << std::flush; + auto usource = o->data; //(UIFrame*)source.get(); + std::cout << "Loaded data into object. " << usource->box.getPosition().x << " " << usource->box.getPosition().y << " " << + usource->box.getSize().x << " " << usource->box.getSize().y << std::endl; + } + else + { + std::cout << "Allocation failed.\n" << std::flush; + } + newobj = (PyObject*)o; + break; + + } case PyObjectsEnum::UICAPTION: + { + std::cout << "UICAPTION case\n"; + PyErr_SetString(PyExc_NotImplementedError, "UICaption class not implemented in Python yet."); + /* not yet implemented PyUICaptionObject* o = (PyUICaptionObject*)PyUICaptionType.tp_alloc(&PyUICaptionType, 0); if (o) o->data = std::static_pointer_cast(source); + */ break; + } case PyObjectsEnum::UISPRITE: + { + std::cout << "UISPRITE case\n"; + PyErr_SetString(PyExc_NotImplementedError, "UISprite class not implemented in Python yet."); + /* PyUISpriteObject* o = (PyUISpriteObject*)PyUISpriteType.tp_alloc(&PyUISpriteType, 0); if (o) o->data = std::static_pointer_cast(source); + */ break; - */ + } default: return NULL; break; diff --git a/src/UI.h b/src/UI.h index ad214dd..c8cf01a 100644 --- a/src/UI.h +++ b/src/UI.h @@ -113,9 +113,9 @@ typedef struct { std::shared_ptr data; } PyUISpriteObject; -PyObject* py_instance(std::shared_ptr source); namespace mcrfpydef { + PyObject* py_instance(std::shared_ptr source); // Color Definitions // struct, members, new, set_member, PyTypeObject @@ -373,11 +373,8 @@ namespace mcrfpydef { return 0; } - static PyObject* PyUIFrame_get_children(PyUIFrameObject* self, void* closure) - { - // create PyUICollection instance pointing to self->data->children - return NULL; - } + static PyObject* PyUIFrame_get_children(PyUIFrameObject*, void*); + // implementation after the PyUICollectionType definition static PyGetSetDef PyUIFrame_getsetters[] = { {"x", (getter)PyUIFrame_get_float_member, (setter)PyUIFrame_set_float_member, "X coordinate of top-left corner", (void*)0}, @@ -424,6 +421,8 @@ namespace mcrfpydef { //self->data->x = x; //self->data->y = y; + self->data->box.setFillColor(sf::Color(0,0,0,255)); + self->data->box.setOutlineColor(sf::Color(128,128,128,255)); return 0; } @@ -509,7 +508,7 @@ namespace mcrfpydef { return NULL; } - if (self->index > self->start_size) + if (self->index > self->start_size - 1) { PyErr_SetNone(PyExc_StopIteration); return NULL; @@ -521,8 +520,9 @@ namespace mcrfpydef { PyErr_SetString(PyExc_RuntimeError, "the collection store returned a null pointer"); return NULL; } - auto target = vec[self->index-1]; + auto target = (*vec)[self->index-1]; // TODO build PyObject* of the correct UIDrawable subclass to return + return py_instance(target); } static PyObject* PyUICollectionIter_repr(PyUICollectionIterObject* self) @@ -588,6 +588,79 @@ namespace mcrfpydef { return NULL; } // build a Python version of item at self->data[index] + // Copy pasted:: + auto vec = self->data.get(); + if (!vec) + { + PyErr_SetString(PyExc_RuntimeError, "the collection store returned a null pointer"); + return NULL; + } + while (index < 0) index += self->data->size(); + if (index > self->data->size() - 1) + { + PyErr_SetString(PyExc_IndexError, "UICollection index out of range"); + return NULL; + } + auto target = (*vec)[index]; + // TODO build PyObject* of the correct UIDrawable subclass to return + //return py_instance(target); + /* + PyTypeObject* colorType = &PyColorType; + PyObject* pyColor = colorType->tp_alloc(colorType, 0); + if (pyColor == NULL) + { + std::cout << "failure to allocate mcrfpy.Color / PyColorType" << std::endl; + return NULL; + } + PyColorObject* pyColorObj = reinterpret_cast(pyColor); + pyColorObj->data = std::make_shared(); + pyColorObj->data-> r = 255; + return (PyObject*)pyColorObj; + */ + + + + + + + PyObject* newobj = NULL; + std::cout << "Instantiating object\n"; + switch (target->derived_type()) + { + case PyObjectsEnum::UIFRAME: + { + std::cout << "UIFRAME case\n" << std::flush; + PyUIFrameObject* o = (PyUIFrameObject*)((&PyUIFrameType)->tp_alloc(&PyUIFrameType, 0)); + if (o) + { + std::cout << "Casting data...\n" << std::flush; + auto p = std::static_pointer_cast(target); + std::cout << "casted. Assigning...\n" << std::flush; + //o->data = std::make_shared(); + + o->data = p; + //std::cout << "assigned.\n" << std::flush; + auto utarget = o->data; //(UIFrame*)target.get(); + std::cout << "Loaded data into object. " << utarget->box.getPosition().x << " " << utarget->box.getPosition().y << " " << + utarget->box.getSize().x << " " << utarget->box.getSize().y << std::endl; + } + else + { + std::cout << "Allocation failed.\n" << std::flush; + } + return (PyObject*)o; + } + } + + + + + + + + return NULL; + + } static PySequenceMethods PyUICollection_sqmethods = { @@ -605,6 +678,7 @@ namespace mcrfpydef { { // if not UIDrawable subclass, reject it // self->data->push_back( c++ object inside o ); + return NULL; // TODO } static PyObject* PyUICollection_remove(PyUICollectionObject* self, PyObject* o) @@ -613,6 +687,7 @@ namespace mcrfpydef { // long index = PyLong_AsLong(o); // if (index >= self->data->size()) { //exception text; return -1; } // release the shared pointer at self->data[index]; + return NULL; // TODO } static PyMethodDef PyUICollection_methods[] = { @@ -694,6 +769,16 @@ namespace mcrfpydef { */ + static PyObject* PyUIFrame_get_children(PyUIFrameObject* self, void* closure) + { + // create PyUICollection instance pointing to self->data->children + PyUICollectionObject* o = (PyUICollectionObject*)PyUICollectionType.tp_alloc(&PyUICollectionType, 0); + if (o) + o->data = self->data->children; + return (PyObject*)o; + } + + } // namespace mcrfpydef