निम्नलिखित कोड अविश्वसनीय रूप से सरल लगता है। पायथन में फ़ंक्शन के लिए एक पूर्णांक पारित किया जाता है, जो C में एक PyList बनाता है और फिर उसे पॉप्युलेट करता है:

hello.c:

#include <Python.h>

PyObject* getlist(int *len)
{
    printf("Passed to C: %d\n", *len);
    PyObject *dlist = PyList_New(*len);
    double num = 0.1;
    for (int i = 0; i < *len; i++)
    {
        PyList_SetItem(dlist, i, PyFloat_FromDouble(num));
        num += 0.1;
    }

    return dlist;
}

static char helloworld_docs[] =
   "Fill docs where possible\n";

static PyMethodDef helloworld_funcs[] = {
   {"getlist", (PyCFunction)getlist, METH_VARARGS, helloworld_docs},
   {NULL}
};

static struct PyModuleDef Helloworld =
{
    PyModuleDef_HEAD_INIT,
    "Helloworld", // module name
    "NULL", // module documentation
    -1,   /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */
    helloworld_funcs
};

PyMODINIT_FUNC PyInit_helloworld(void)
{
    return PyModule_Create(&Helloworld);
}

setup.py:

from distutils.core import setup
from distutils.extension import Extension

setup(name='helloworld', 
      version='1.0', 
      ext_modules=[Extension('helloworld', ['hello.c'])])

usepkg.py:

#!/usr/bin/python
import sys
import helloworld
print("Input to Python:", sys.argv[1])
print (helloworld.getlist(sys.argv[1]))

मैं का उपयोग कर निर्माण और स्थापित करता हूं

python3 setup.py build
python3 setup.py install

और मुझे कोई त्रुटि नहीं दिख रही है।

जब मैं इसका परीक्षण करता हूं तो अजीब व्यवहार होता है। उदाहरण के लिए:

python3 usepkg.py 4

कोई फर्क नहीं पड़ता कि मैं तर्क के रूप में क्या मूल्य देता हूं, आउटपुट हमेशा वही होता है:

Input to Python: 4
Passed to C: 6
[0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6]

C को दिया गया मान हमेशा 6 होता है। यह वही है चाहे इनपुट agument int हो या Py_ssize_t। मैं क्या खो रहा हूँ?

2
Sartorible 9 सितंबर 2020, 00:04

1 उत्तर

सबसे बढ़िया उत्तर

मुझे आश्चर्य है कि निर्माण करते समय यहां कोई चेतावनी नहीं है, कार्यों के प्रकार उनके आदिम प्रकार नहीं होने चाहिए, लेकिन PyObject* - फिर आप प्रकारों को पार्स करेंगे और अपना कार्य निष्पादित करेंगे

यहां आपके फ़ंक्शन में समायोजन है:

PyObject* getlist(PyObject* self, PyObject* args)
{
    int len;
    if (!PyArg_ParseTuple(args, "i", &len)) {
        return NULL;
    }
    printf("Passed to C: %d\n", len);
    PyObject *dlist = PyList_New(len);
    double num = 0.1;
    for (int i = 0; i < len; i++)
    {
        PyList_SetItem(dlist, i, PyFloat_FromDouble(num));
        num += 0.1;
    }

    return dlist;
}

इसके बारे में अधिक जानकारी पार्सिंग तर्कों और मूल्यों के निर्माण में मिल सकती है। प्रलेखन


आपको जो संख्या मिल रही थी, वह संभवतः PyObject*->ob_refcount के self (C मॉड्यूल के संदर्भों की संख्या) में मान था

मेरे मामले में मैंने ६ के बजाय ४ देखा, हालांकि मैं संभवतः अजगर और/या कॉलिंग दृष्टिकोण के एक अलग संस्करण का उपयोग कर रहा हूं

4
Anthony Sottile 9 सितंबर 2020, 00:14