How to have a pointer on the C / C ++ side in Python.
Something wants to use a C ++ class from Python.
class Hello {
public:
void hello();
};
PyCapsule_New
Use PyCapsule_New
to return a C / C ++ pointer asPyObject *
.
static void py_hello_free(PyObject *obj);
static PyObject* py_hello_alloc(PyObject *self, PyObject *args)
{
// Allocate a new C++ pointer h as a Python object "_Hello"
Hello* const h= new Hello();
return PyCapsule_New(h, "_Hello", py_hello_free);
}
If you pass a function that releases the pointer, Python will release it. If you manage the memory on the C / C ++ side and do not need to release it, you can pass NULL instead of py_hello_free.
void py_hello_free(PyObject *obj)
{
// Destructor function for _Hello pointer, called automatically from Python
Hello* const h= (Hello*) PyCapsule_GetPointer(obj, "_Hello");
delete h;
}
PyCapsule_GetPointer
To return to a C / C ++ pointer PyCapsule_GetPointer
:
PyObject* py_hello(PyObject *self, PyObject *args)
{
// Use _Hello pointer from Python
PyObject* py_obj;
if(!PyArg_ParseTuple(args, "O", &py_obj))
return NULL;
Hello* h= (Hello*) PyCapsule_GetPointer(py_obj, "_Hello");
if(h == 0) return NULL;
h->hello();
Py_RETURN_NONE;
}
#include <cstdio>
#include "Python.h"
// ...Code above...
static PyMethodDef methods[] = {
{"hello_alloc", py_hello_alloc, METH_VARARGS, "allocate a Hello object"},
{"hello", py_hello, METH_VARARGS, "call hello() method"},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef module = {
PyModuleDef_HEAD_INIT,
"cext02", // name of this module
"Use C/C++ pointer", // Doc String
-1,
methods
};
PyMODINIT_FUNC
PyInit_cext02(void) {
return PyModule_Create(&module);
}
The usual setup.py
from distutils.core import setup, Extension
setup(name='cext02',
version='0.0.1',
description='c_ext02 pointer',
author='Jun Koda',
url='https://github.com/junkoda/python_c_ext',
ext_modules=[
Extension('cext02', ['cext02.cpp'])
]
)
compile
$ python3 setup.py build_ext --inplace
import cext02 #Extension by C
h = cext02.hello_alloc() # h = new Hello()Something like
cext02.hello(h) # h->hello()Call
Use like. (Of course, if you wrap it in a Python class, you can use it like an object.)
--Before you start extending C, you should read the Python Cookbook first. Python Cookbook 3rd Edition (O'Reilly)
Recommended Posts