Python Forum
How to create ctypes.c_void_p object from C++ and set it as claas attribute - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: How to create ctypes.c_void_p object from C++ and set it as claas attribute (/thread-1864.html)



How to create ctypes.c_void_p object from C++ and set it as claas attribute - lfdm - Jan-31-2017

Hi,

I'm embedding the Python interpreter into a C++ application. The target is to be able to prototype with arrayfire.

What I'm trying to do is pass an af::array from C++ to Python, do some computation and return something.

The arrayfire python bindings define an Array class which holds an attribute being the af::array reference. This attribute type is ctypes.c_void_p.

The Python code for this class base class is:
from .library import *
from .util import *

class BaseArray(object):
    """
    Base array class for arrayfire. For internal use only.
    """
    def __init__(self):
        self.arr = c_void_ptr_t(0)

[/icode]


I made a test script which looks like this:
[icode]import arrayfire as af
def test_Array(array):
    return af.min(array)
[/icode]

My C++ code looks like this:
[icode]int Interpreter::testArray()
{
    af::array myArray = af::seq(5, 10, 1);

    // Create arrayfire array and set 
    PyObject* afArray = createObject("arrayfire", "Array");

    // The 'arr' attribute is holding the af_array reference
    PyObject* attr = PyObject_GetAttrString(afArray, "arr");

    // Build an attribute object with our AF array reference
    PyObject* capsule = PyCapsule_New(myArray.get(), "c_void_p", nullptr);
    PyObject* attrObj = createObject("ctypes", "c_void_p", Py_BuildValue("(O)", capsule));

    // Set 'arr'
    int results = PyObject_SetAttr(afArray, PyUnicode_FromString("arr"), attrObj);

    // Call test function
    PyObject *pFunc = PyObject_GetAttrString(m_module, "test_Array");
    PyObject *pArgs = Py_BuildValue("(O)", afArray);

    if (pFunc)
    {
        PyObject *pResult = PyObject_CallObject(pFunc, pArgs);

        if (pResult)
        {
            float res = PyFloat_AsDouble(pResult);
            qDebug() << "Array min: " << res;
        }
        else
        {
            getError();
        }
        Py_XDECREF(pResult);
    }

    //...
    return 0;
}

PyObject* Interpreter::createObject(const QString& module, const QString& name, PyObject* args /*= nullptr*/)
{
    PyObject* pName = nullptr;
    PyObject* pModule = nullptr;
    PyObject* pDict = nullptr;
    PyObject* pClass = nullptr;
    PyObject* pInstance = nullptr;

    // Build the name object
    pName = PyUnicode_FromString(module.toLatin1());

    // Load the module object
    pModule = PyImport_Import(pName);

    if (!pModule)
    {
        qDebug() << "Unknown module name";
        return pInstance;
    }

    // pDict is a borrowed reference
    pDict = PyModule_GetDict(pModule);

    // Build the name of a callable class
    pClass = PyDict_GetItemString(pDict, name.toLatin1());

    // Create an instance of the class
    if (PyCallable_Check(pClass))
    {
        pInstance = PyObject_CallObject(pClass, args);
    }
    else
    {
        qDebug() << "Cannot instantiate the Python object";
    }

    return pInstance;
}
What is the proper way to set this arr attribute with a void*?

Thanks


RE: How to create ctypes.c_void_p object from C++ and set it as claas attribute - Larz60+ - Jan-31-2017

You need to place :'[code]'


at the start of code blocks you finish ok
but left out the start tag


RE: How to create ctypes.c_void_p object from C++ and set it as claas attribute - lfdm - Feb-02-2017

In response to my original question here's the code
//...

// The 'arr' attribute is holding the af_array reference
PyObject* attr = PyObject_GetAttrString(afArray, "arr");

// Build an attribute object with our AF array reference
PyObject* ctypes_mod = PyImport_ImportModule("ctypes");
PyObject* c_void_p = PyObject_GetAttrString(ctypes_mod, "c_void_p");
PyObject* p = PyObject_CallFunction(c_void_p, "O", PyLong_FromVoidPtr(my_void*));

// Set 'arr'
int results = PyObject_SetAttr(afArray, PyUnicode_FromString("arr"), p);
// ...