Python C wrapper for reading variable argument lengths

和自甴很熟 提交于 2021-02-04 08:33:19

问题


I am trying to replace MATLAB/MEX and switch to Python. I came across SWIG, ctypes & Cython as possible solutions and started trying out SWIG (which seems very simple).

My C functions have variable argument lengths of the form main(int argc, char *argv[]). I found solutions online, but getting this working with SWIG lead to a lot of issues.

  1. Are the other methods (ctypes / Cython) any simpler?
  2. Any example to do this task with SWIG will be helpful.

回答1:


There's actually an example in the SWIG documentation for exactly this sort of function with Python. I've quoted it here with a minor change:

%typemap(in) (int argc, char *argv[]) {
  int i;
  if (!PyList_Check($input)) {
    PyErr_SetString(PyExc_ValueError, "Expecting a list");
    return NULL;
  }
  $1 = PyList_Size($input);
  $2 = (char **) malloc(($1+1)*sizeof(char *));
  for (i = 0; i < $1; i++) {
    PyObject *s = PyList_GetItem($input,i);
    if (!PyString_Check(s)) {
        free($2);
        PyErr_SetString(PyExc_ValueError, "List items must be strings");
        return NULL;
    }
    $2[i] = PyString_AsString(s);
  }
  $2[i] = 0;
}

%typemap(freearg) (int argc, char *argv[]) {
   free($2); // If here is uneeded, free(NULL) is legal
}

This allows you in Python to do simply:

import test
test.foo(["a", "b", "c"])

Where test is the name of the module you gave SWIG and foo is a function that matches the signature int argc, char *argv[]. Simple and intuitive to use for a Python programmer and it encapsulates and reuses the complex bit.


What the documentation doesn't seem to mention though is that there's an interface file that does all this for you already:

%module test

%include <argcargv.i>

%apply (int ARGC, char **ARGV) { (int argc, char *argv[]) }

void foo(int argc, char *argv[]);

is sufficient.




回答2:


Here is a sample by using ctypes.

First the c code, it must not change the content of argv:

#include <stdio.h>
void test(int n, char *argv[])
{
    int i;
    for(i=0;i<n;i++)
    {
        printf("%s\n", argv[i]);
    }
}

Then you can call this c function by the following python code:

from ctypes import *
dll = cdll.LoadLibrary("charpp_test.dll") 
argv = ["test1", "testtest2", "testtesttest3"]
dll.test(len(argv), (c_char_p*len(argv))(*argv))


来源:https://stackoverflow.com/questions/11641161/python-c-wrapper-for-reading-variable-argument-lengths

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!