0

I'm trying to create a shared object with Python to read a CSV file to be used by a C application.

I'm having a really hard time doing this.

My code is here:

from cffi import FFI
import csv
import io

ffi = FFI()

ffi.cdef("""
void processCsv(const char[], const char[], const char[]);
void processCsvFile(const char[], const char[], const char[]);
""")

def process_csv(csv_data, selected_columns, row_filter_definitions):
    # Parse the CSV data
    csv_reader = csv.DictReader(io.StringIO(csv_data.decode('utf-8')))
    headers = csv_reader.fieldnames

    # Parse selected columns
    if selected_columns:
        selected_columns = selected_columns.decode('utf-8').split(',')
    else:
        selected_columns = headers

    # Parse filters
    filters = []
    if row_filter_definitions:
        for line in row_filter_definitions.decode('utf-8').split('\n'):
            if line:
                if '=' in line:
                    header, value = line.split('=')
                    op = '='
                elif '>' in line:
                    header, value = line.split('>')
                    op = '>'
                elif '<' in line:
                    header, value = line.split('<')
                    op = '<'
                filters.append((header, op, value))

    # Apply filters and select columns
    output = io.StringIO()
    csv_writer = csv.DictWriter(output, fieldnames=selected_columns)
    csv_writer.writeheader()
    
    for row in csv_reader:
        match = all((op == '=' and row[header] == value) or 
                    (op == '>' and row[header] > value) or 
                    (op == '<' and row[header] < value) for header, op, value in filters)
        if match:
            csv_writer.writerow({col: row[col] for col in selected_columns})

    print(output.getvalue(), end='')

def process_csv_file(csv_file_path, selected_columns, row_filter_definitions):
    with open(csv_file_path.decode('utf-8'), 'r') as f:
        process_csv(f.read().encode('utf-8'), selected_columns, row_filter_definitions)

ffi.set_source("_csv_processor",
"""
#include <stdio.h>

void process_csv(const char csv[], const char selectedColumns[], const char rowFilterDefinitions[]);
void process_csv_file(const char csvFilePath[], const char selectedColumns[], const char rowFilterDefinitions[]);

void processCsv(const char csv[], const char selectedColumns[], const char rowFilterDefinitions[]) {
    process_csv(csv, selectedColumns, rowFilterDefinitions);
}

void processCsvFile(const char csvFilePath[], const char selectedColumns[], const char rowFilterDefinitions[]) {
    process_csv_file(csvFilePath, selectedColumns, rowFilterDefinitions);
}
""")

if __name__ == "__main__":
    ffi.compile(verbose=True)

And I'm generating this code with:

python3 csv_processor.py

When I try:

gcc -o programa_c programa_c.c -L. -l_csv_processor -lpython3.10

I receive this error:

/27818bb096b67c55a7a954c23cec29630e6d644e$ gcc -o programa_c programa_c.c -L. -l_csv_processor -lpython3.10
  /usr/bin/ld: cannot find -l_csv_processor: No such file or directory
  collect2: error: ld returned 1 exit status

The code in C is here:

#include <stdio.h>

void processCsv(const char[], const char[], const char[]);
void processCsvFile(const char[], const char[], const char[]);

int main(){
    const char csv[] = "header1,header2,header3\n1,2,3\n4,5,6\n7,8,9";processCsv(csv, "header1,header3", "header1>1\nheader3<9");
    const char csv_file[] = "data.csv";
processCsvFile(csv_file, "header1,header3", "header1>1\nheader3<9");
    return 0;
}

and I need:

  • Implement a library that processes CSV files, applying filters and selecting columns as specified. The solution must be able to integrate with the interface defined in C below.

c /** * Process the CSV data by applying filters and selecting columns. * * @param csv The CSV data to be processed. * @param selectedColumns The columns to be selected from the CSV data. * @param rowFilterDefinitions The filters to be applied to the CSV data.

    • @return void */ void processCsv(const char[], const char[], const char[]);

/** * Process the CSV file by applying filters and selecting columns.

    • @param csvFilePath The path to the CSV file to be processed. * @param selectedColumns The columns to be selected from the CSV data.
  • @param rowFilterDefinitions The filters to be applied to the CSV data. * * @return void */ void processCsvFile(const char[], const char[], const char[]);

processCsv

  • csv: String with CSV data, where each line represents a record and the columns are separated by commas.
    • Example: "header1,header2,header3\n1,2,3\n4,5,6"
  • selectedColumns: A string where the names of the columns to be selected are separated by commas.
    • Example: "header1,header3"
  • rowFilterDefinitions: A string where each filter is defined on a new line, in the format header(comparador)valor.
    • Example: "header1>1\nheader2=2\nheader3<6"

processCsvFile

  • csvFilePath: String with the CSV file path.
    • Example: "path/to/csv_file.csv"
  • selectedColumns: A string where the names of the columns to be selected are separated by commas.
    • Example: "header1,header3"
  • rowFilterDefinitions: A string where each filter is defined on a new line, in the format header(comparador)valor.
    • Example: "header1>1\nheader2=2\nheader3<6"

I don't know where I could be going wrong, as I've never worked with this type of application, it's the first time

2

0

Browse other questions tagged or ask your own question.