Skip to content

Native python extensions using OCP - issues with casting [was: Getting a Reference to the Underlying OCCT C++ Instance] #127

Closed
@jmwright

Description

@jmwright

I've written an experimental C++ app that uses the Python interpreter and the OCCT 3D viewer together so that it can be a visual REPL for CadQuery. I have implemented a C++ callback for show_object so that the Python code can call show_object(res) to pass the cadquery.Workplane or cadquery.Assembly object to the C++ side. Things work up to a point, but I have struggled getting an OCCT TopoDS_Solid/Shape from OCP to pass to the viewer code. Is there an equivalent of the wrapped attribute on CadQuery objects that will return the underlying C++ instance? Below is a rough implementation of the show_object callback where I am just trying to use pybind11 to get a reference to the underlying OCCT instance to pass to the viewer, which gives me an error that the OCP type cannot be cast to the OCCT type.

static PyObject* show_show_object(PyObject *self, PyObject *args)
{
    // Get the argument back from the Python show_object call
    PyObject* i;
    if(!PyArg_ParseTuple(args, "O", &i))
        return NULL;

    // Handle a Workplane object differently than an Assembly object
    PyTypeObject* type = i->ob_type;
    if (strcmp(type->tp_name, "Workplane") == 0) {
        printf("cadquery.Workplane object detected.\n");
        PyObject* obj = PyObject_CallMethod(i, "val", NULL);
        if (obj == NULL) {
            printf("Error getting wrapped object from cq.Workplane.\n");
        }
        else {
            PyObject* wrapped = PyObject_GetAttrString(obj, "wrapped");
            if (wrapped != NULL) {
                if (strcmp(wrapped->ob_type->tp_name, "OCP.TopoDS.TopoDS_Solid") == 0) {
                    printf("Found OCP TopoDS_Solid object.\n");
                    py::handle h = wrapped;
                    TopoDS_Shape* x = *py::cast<TopoDS_Shape>(h);
                }
                else {
                    printf("Found some other TopoDS object.\n");
                }
            }
        }
    }
    else if (strcmp(type->tp_name, "Assembly") == 0) {
        printf("cadquery.Assembly object detected.\n");
    }

    return args;
}

The output, including the error, is below.

cadquery.Workplane object detected.
Found OCP TopoDS_Solid object.
terminate called after throwing an instance of 'pybind11::cast_error'
  what():  Unable to cast Python instance of type <class 'OCP.TopoDS.TopoDS_Solid'> to C++ type 'TopoDS_Shape'
Aborted

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions