1

Refering to http://mail.python.org/pipermail/python-dev/2009-June/090210.html AND http://dan.iel.fm/posts/python-c-extensions/

and here is other places i searched regarding my question: http://article.gmane.org/gmane.comp.python.general/424736 http://joyrex.spc.uchicago.edu/bookshelves/python/cookbook/pythoncook-CHP-16-SECT-3.html http://docs.python.org/2/c-api/sequence.html#PySequence_Check Python extension module with variable number of arguments

I am inexperienced in Python/C API.

I have the following code:

sm_int_list = (1,20,3)
c_int_array = (ctypes.c_int * len(sm_int_list))(*sm_int_list)
sm_str_tuple = ('some','text', 'here')

On the C extension side, i have done something like this:

static PyObject* stuff_here(PyObject *self, PyObject *args)
{
    char* input;
    int *i1, *i2;
    char *s1, *s2;
    // args = (('some','text', 'here'), [1,20,3], ('some','text', 'here'), [1,20,3])
    **PyArg_ParseTuple(args, "(s#:):#(i:)#(s#:):#(i:)#", &s1, &i1, &s2, &i2)**;
/*stuff*/
}

such that: stuff.here(('some','text', 'here'), [1,20,3], ('some','text', 'here'), [1,20,3])

returns data in the same form as args after some computation. I would like to know the PyArg_ParseTuple expression, is it the proper way to parse

  1. an array of varying string
  2. an array of integers

UPDATE NEW

Is this the correct way?:

static PyObject* stuff_here(PyObject *self, PyObject *args)
    unsigned int tint[], cint[];
    ttotal=0, ctotal=0;
    char *tstr, *cstr;
    int *t_counts, *c_counts;
    Py_ssize_t size;
    PyObject *t_str1, *t_int1, *c_str2, *c_int2; //the C var that takes in the py variable value
    PyObject *tseq, cseq;
    int t_seqlen=0, c_seqlen=0;

if (!PyArg_ParseTuple(args, "OOiOOi", &t_str1, &t_int1, &ttotal,  &c_str2, &c_int2, &ctotal))
    {
        return NULL;
    }

if (!PySequence_Check(tag_str1) && !PySequence_Check(cat_str2)) return NULL;

    else:
    {
        //All things t
        tseq = PySequence_Fast(t_str1, "iterable");
        t_seqlen = PySequence_Fast_GET_SIZE(tseq);
        t_counts = PySequence_Fast(t_int1);

        //All things c
        cseq = PySequence_Fast(c_str2);
        c_seqlen = PySequence_Fast_GET_SIZE(cseq);
        c_counts = PySequence_Fast(c_int2);

        //Make c arrays of all things tag and cat
        for (i=0; i<t_seqlen; i++)
        {
            tstr[i] = PySequence_Fast_GET_ITEM(tseq, i);
            tcounts[i] = PySequence_Fast_GET_ITEM(t_counts, i);
        }

        for (i=0; i<c_seqlen; i++)
        {
            cstr[i] = PySequence_Fast_GET_ITEM(cseq, i);
            ccounts[i] = PySequence_Fast_GET_ITEM(c_counts, i);
        }


    }

OR

PyArg_ParseTuple(args, "(s:)(i:)(s:)(i:)", &s1, &i1, &s2, &i2)

And then again while returning,

Py_BuildValue("sisi", arr_str1,arr_int1,arr_str2,arr_int2) ??

Infact if someone could in detail clarify the various PyArg_ParseTuple function that would be of great benefit. the Python C API, as i find it in the documentation, is not exactly a tutorial on things to do.

Community
  • 1
  • 1
user2290820
  • 2,709
  • 5
  • 34
  • 62

1 Answers1

1

You can use PyArg_ParseTuple to parse a real tuple, that has a fixed structure. Especially the number of items in the subtuples cannot change.

As the 2.7.5 documentation says, your format "(s#:):#(i:)#(s#:):#(i:)#" is wrong since : cannot occur in nested parenthesis. The format "(sss)(iii)(sss)(iii)", along with total of 12 pointer arguments should match your arguments. Likewise for Py_BuildValue you can use the same format string (which creates 4 tuples within 1 tuple), or "(sss)[iii](sss)[iii]" if the type matters (this makes the integers to be in lists instead of tuples).