Skip to content

Instantly share code, notes, and snippets.

@VehpuS
Created February 8, 2019 23:51
Show Gist options
  • Save VehpuS/76e5d6edb3acbd3976daac53c0340dcc to your computer and use it in GitHub Desktop.
Save VehpuS/76e5d6edb3acbd3976daac53c0340dcc to your computer and use it in GitHub Desktop.
A CSV parser in C using the Python csv standard module
#include <Python.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define bail_null(obj) \
if (NULL == obj) { err = 1; goto bail; }
#define bail_require(cond) \
if (!(cond)) { err = 1; goto bail; }
static int try_python(const char* dbPath);
static int try_python(const char* dbPath) {
int err = 0;
PyObject *csvModule, *getReader, *dbFile, *reader;
PyObject *pArgs, *iterator, *item;
char fileName[1000] = {'\0'};
char mode[] = "rbZ";
strncpy(fileName, dbPath, sizeof(fileName));
Py_Initialize();
// https://docs.python.org/2.7/library/csv.html
csvModule = PyImport_ImportModule("csv");
bail_null_msg(csvModule, "Failed to import CSV parser modules");
getReader = PyObject_GetAttrString(csvModule, "reader");
bail_null(getReader);
bail_require(PyCallable_Check(getReader));
/* getReader is a new reference */
dbFile = PyFile_FromString(fileName, mode);
bail_null(dbFile);
pArgs = PyTuple_New(1);
bail_null(pArgs);
PyTuple_SetItem(pArgs, 0, dbFile);
reader = PyObject_CallObject(getReader, pArgs);
bail_null(reader);
bail_require(PyIter_Check(reader));
iterator = PyObject_GetIter(reader);
bail_null(iterator);
while ((item = PyIter_Next(iterator))) {
PyObject* iteratorString = PyObject_Str(item);
const char* s = PyString_AsString(iteratorString);
printf("%s\n", s);
Py_DECREF(iteratorString);
Py_DECREF(item);
}
bail:
if (reader) {
Py_DECREF(reader);
}
if (dbFile) {
Py_DECREF(dbFile);
}
if (getReader) {
Py_XDECREF(reader);
}
if (csvModule) {
Py_DECREF(csvModule);
}
if (err) {
PyErr_Print();
}
Py_Finalize();
return err;
}
int main(int argc, char *argv[]) {
int err = 0;
printf("test python CSV parser from C.\n");
if (argc < 2 || NULL == argv[1]) {
printf("You need to call this binary with a path to a CSV file.\n\n");
err = 1;
} else {
err = try_python(argv[1]);
}
return err;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment