char **argv parsing

Asked by Baurzhan Muftakhidinov

Hello,

I have a function declared as
extern int ginit ( char *project, int argc, char **argv );

While autoscanning I get an error

WrapperWarning: Parameter 'char * * argv' error (used in extern int ginit(char * project, int argc, char * * argv) [free function]): TypeLookupError(['char * *'],)

So I wonder, is **argv not implemented?

Thanks

Question information

Language:
English Edit question
Status:
Answered
For:
PyBindGen Edit question
Assignee:
No assignee Edit question
Last query:
Last reply:
Revision history for this message
Baurzhan Muftakhidinov (baurthefirst) said :
#1

Ok, now I see this error message is coming from pygccxml.

Revision history for this message
Gustavo Carneiro (gjc) said :
#2

Sorry, char ** is not supported, but you can plug in your own type handler. Here's one that I uses in the ns-3 project:

class ArgvParam(Parameter):
    """
    Converts a python list-of-strings argument to a pair of 'int argc,
    char *argv[]' arguments to pass into C.

    One Python argument becomes two C function arguments -> it's a miracle!

    Note: this parameter type handler is not registered by any name;
    must be used explicitly.
    """

    DIRECTIONS = [Parameter.DIRECTION_IN]
    CTYPES = []

    def convert_c_to_python(self, wrapper):
        raise NotImplementedError

    def convert_python_to_c(self, wrapper):
        py_name = wrapper.declarations.declare_variable('PyObject*', 'py_' + self.name)
        argc_var = wrapper.declarations.declare_variable('int', 'argc')
        name = wrapper.declarations.declare_variable('char**', self.name)
        idx = wrapper.declarations.declare_variable('Py_ssize_t', 'idx')
        wrapper.parse_params.add_parameter('O!', ['&PyList_Type', '&'+py_name], self.name)
        wrapper.before_call.write_code("%s = (char **) malloc(sizeof(char*)*PyList_Size(%s));"
                                       % (name, py_name))
        wrapper.before_call.add_cleanup_code('free(%s);' % name)
        wrapper.before_call.write_code('''
for (%(idx)s = 0; %(idx)s < PyList_Size(%(py_name)s); %(idx)s++)
{
''' % vars())
        wrapper.before_call.sink.indent()
        wrapper.before_call.write_code('''
PyObject *item = PyList_GET_ITEM(%(py_name)s, %(idx)s);
''' % vars())
        wrapper.before_call.write_error_check(
            '!PyString_Check(item)',
            failure_cleanup=('PyErr_SetString(PyExc_TypeError, '
                             '"argument %s must be a list of strings");') % self.name)
        wrapper.before_call.write_code(
            '%s[%s] = PyString_AsString(item);' % (name, idx))
        wrapper.before_call.sink.unindent()
        wrapper.before_call.write_code('}')
        wrapper.before_call.write_code('%s = PyList_Size(%s);' % (argc_var, py_name))

        wrapper.call_params.append(argc_var)
        wrapper.call_params.append(name)

Here's it being used (manually). Note that a single ArgvParam takes a single Python `argv` parameter and converts into a pair of argc and argv parameters in the C side:

    CommandLine.add_method('Parse', None, [ArgvParam(None, 'argv')], is_static=False)

Can you help with this problem?

Provide an answer of your own, or ask Baurzhan Muftakhidinov for more information if necessary.

To post a message you must log in.