I am building a Python extension (.pyd
) using Visual Studio 2015 C++ project and Python 2.7 32bit.
This is my .cpp
file:
#include <Python.h>
static PyObject* GetTwoInts(PyObject* self, PyObject* args)
{
srand(time(NULL));
int random1 = rand() % 10;
int random2 = rand() % 10;
PyObject * python_val = Py_BuildValue("ii", random1, random2);
return python_val;
}
static PyObject* GetListTwoInts(PyObject* self, PyObject* args)
{
srand(time(NULL));
int random1 = rand() % 10;
int random2 = rand() % 10;
PyObject *val1 = PyInt_FromLong(random1);
PyObject *val2 = PyInt_FromLong(random2);
PyObject *result = PyList_New(2);
PyList_SetItem(result, 0, val1);
PyList_SetItem(result, 1, val2);
PyObject * python_val = Py_BuildValue("ii", result);
return python_val;
}
PyMODINIT_FUNC initUtils(void)
{
static PyMethodDef methods[] = {
{ "GetTwoInts", GetTwoInts, METH_NOARGS,
"Get two C ints as a Python tuple with two random numbers" },
{ "GetListTwoInts", GetListTwoInts, METH_NOARGS,
"Get a list with two random numbers" },
{ NULL, NULL, 0, NULL },
};
PyObject *m = Py_InitModule("Utils", methods);
}
This is the Python source code using the compiled extension:
import sys
import Utils
print help(Utils)
print Utils.GetTwoInts()
print Utils.GetListTwoInts()
This is the output:
(4, 2)
(91213912, 91213912)
So, the Py_BuildValue("ii", random1, random2);
gave me a proper tuple with two random ints, just as expected. However, returning a list in the GetListTwoInts
method gives me invalid numbers (looks like a reference value or a pointer?).
What should I do to return a list of real values instead in the GetListTwoInts
method?
You can change the format of Py_BuildValue
so that it builds a list instead of a tuple. Just use "[ii]"
instead of "ii"
as first argument:
static PyObject* GetListTwoInts(PyObject* self, PyObject* args)
{
srand(time(NULL));
int random1 = rand() % 10;
int random2 = rand() % 10;
PyObject * python_val = Py_BuildValue("[ii]", random1, random2);
return python_val;
}
You can use PyList_New
and PyList_SetItem
if you want to create a list of dynamic size.
static PyObject* GetList(PyObject* self, PyObject* args)
{
srand(time(NULL));
int const N = 10;
PyObject* python_val = PyList_New(N);
for (int i = 0; i < N; ++i)
{
int r = rand() % 10;
PyObject* python_int = Py_BuildValue("i", r);
PyList_SetItem(python_val, i, python_int);
}
return python_val;
}
The problem with the PyList
version in your question is that you are using Py_BuildValue("ii", result)
on the list. This tries to create a tuple of two integers, where the first value is the result
pointer casted to an integer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With