Как вернуть список целых в расширении Python C API с помощью PyList? - PullRequest
0 голосов
/ 03 июня 2018

Я создаю расширение Python (.pyd) с использованием проекта Visual Studio 2015 C ++ и 32-битного Python 2.7.

Это мой .cpp файл:

#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);
}

Этоисходный код Python с использованием скомпилированного расширения:

import sys
import Utils
print help(Utils)
print Utils.GetTwoInts()
print Utils.GetListTwoInts()

Это вывод:

(4, 2)
(91213912, 91213912)

Итак, Py_BuildValue("ii", random1, random2); дал мне правильный кортеж с двумя случайными числами, так же, какожидается.Тем не менее, возвращая список в методе GetListTwoInts, я получаю недопустимые числа (выглядит как ссылочное значение или указатель?).

Что мне следует сделать, чтобы вместо списка GetListTwoInts вернуть список реальных значенийметод?

1 Ответ

0 голосов
/ 04 июня 2018

Вы можете изменить формат Py_BuildValue, чтобы он создавал список вместо кортежа.Просто используйте "[ii]" вместо "ii" в качестве первого аргумента:

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;
}

Вы можете использовать PyList_New и PyList_SetItem, если хотите создать список динамического размера.

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;
}

Проблема с версией PyList в вашем вопросе заключается в том, что вы используете Py_BuildValue("ii", result) в списке.Это попытается создать кортеж из двух целых чисел, где первое значение - это указатель result, приведенный к целому числу.

...