鍍金池/ 問答/Python  C/ 在C與python交互時(shí),如何實(shí)現(xiàn)參數(shù)個(gè)數(shù)不確定的傳遞?

在C與python交互時(shí),如何實(shí)現(xiàn)參數(shù)個(gè)數(shù)不確定的傳遞?

在python中調(diào)用C實(shí)現(xiàn)的模塊,想在python和C之間根據(jù)需要傳遞參數(shù),但參數(shù)個(gè)數(shù)是不確定的,可以變化的。請(qǐng)問該如何實(shí)現(xiàn)?

現(xiàn)在看到的接口都是得確定參數(shù)個(gè)數(shù),并且需要指定參數(shù)類型的,比如:
PyArg_ParseTuple(pTuple, "ifs" , &i, &f, &s)。

或者簡(jiǎn)化到,傳遞的參數(shù)類型是一致的,但是參數(shù)個(gè)數(shù)可變?cè)撊绾螌?shí)現(xiàn)?
比如說有時(shí)希望傳遞10個(gè)整數(shù),下次希望傳遞20個(gè)參數(shù)?

回答
編輯回答
玩控

傳入可變參數(shù)時(shí),用 PyTuple_Size() 獲取參數(shù)個(gè)數(shù),然后用 PyTuple_GetItem() 循環(huán)讀取每個(gè)參數(shù)值,最后根據(jù)情況轉(zhuǎn)換參數(shù)值。

請(qǐng)參考下面的代碼

/*
此 python 擴(kuò)展示例代碼,計(jì)算整數(shù)數(shù)組和,如下:
    from liyi import psum
    psum(1, 2)
    psum(10, 20, 30)
    try:
        psum('a', 1)
    except TypeError:
        pass


## 編譯命令(以 linux 為例)
cc -g -Wall `python3.6-config --cflags` -o demo demo.c  `python3.6-config --ldflags`


## 參考
https://docs.python.org/3/c-api/index.html
 */
#include <Python.h>


// 計(jì)算整數(shù)數(shù)組和
static PyObject* psum(PyObject *self, PyObject *args)
{
    int sum = 0;
    for (int i=0; i<PyTuple_Size(args); i++) {
        PyObject *item = PyTuple_GetItem(args, i);
        // 數(shù)組元素必須是整型
        if (!PyLong_Check(item)) {
            char message[128];
            snprintf(message, sizeof(message), "%d-th item must be long", i);
            PyErr_SetString(PyExc_TypeError, message);
            return NULL;
        }
        sum += PyLong_AsLong(item);
    }
    return PyLong_FromLong(sum);
}

static PyMethodDef Methods[] = {
    {"psum", psum, METH_VARARGS, "Return sum of integer array"},
    {NULL, NULL, 0, NULL}
};

static PyModuleDef Module = {
    PyModuleDef_HEAD_INIT,
    "liyi", NULL, -1, Methods,
    NULL, NULL, NULL, NULL
};

static PyObject* PyInit(void)
{
    return PyModule_Create(&Module);
}

int main(int argc, char *argv[])
{
    PyImport_AppendInittab("liyi", &PyInit);

    Py_Initialize();
    PyRun_SimpleString(
        "from liyi import psum\n"
        "for numbers in [(1,2), (10,20,30)]:\n"
        "    print('%s = %d' % ('+'.join(map(str, numbers)), psum(*numbers)))\n"
        "try:\n"
        "    psum('a', 1)\n"
        "except TypeError:\n"
        "    import traceback; traceback.print_exc()\n"
    );
    if (Py_FinalizeEx() < 0) {
        exit(1);
    }
    return 0;
}
2017年10月21日 03:17