Home > OS >  How to properly wrap a two dimensional vector using %template
How to properly wrap a two dimensional vector using %template

Time:09-14

I'm trying to make a basic csv parser in c for a particular csv schema, and I'm trying to wrap the function for Python, but I keep getting a "StdVectorTraits not found" warning after wrapper generation. The wrapper is still able to be compiled using g , but when I try to import the underlying shared object using the object.py script, I get "ImportError: undefined symbol: _Z8myVectorRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE"

This is the swig interface file:

%module parser;

%include "/usr/share/swig4.0/std/std_vector.i";
%include "/usr/share/swig4.0/std/std_iostream.i";
%include "/usr/share/swig4.0/std/std_sstream.i";
%include "/usr/share/swig4.0/std/std_string.i";
%include "/usr/share/swig4.0/std/std_basic_string.i";

%{
#include <vector>
#include <fstream>
#include <sstream>
#include <iostream>

std::vector<std::vector<double>> myVector(std::string&);
%}


%template(doubleVector) std::vector<double>;
%template(doubleVecVector) std::vector<std::vector<double>>;

std::vector<std::vector<double>> myVector(std::string& path)
{
    std::ifstream file;
    std::string read;
    std::vector<std::vector<double>> data;
        file.open(path);

        for (int i = 0; i < 21; i  )
        {
            std::getline(file, read);
        }

        for (int i = 0; i < 32; i  )
        {
            std::vector<double> line;
            std::getline(file, read);
            std::stringstream ss(read);

            for (int j = 0; j < 48; j  )
            {
                std::getline(ss, read, ',');
                line.push_back(std::stof(read));
            }
        
            data.push_back(line);
        }

        file.close();

    return data;
}

Error:

---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
/home/../test.ipynb Cell 1 in <cell line: 1>()
----> 1 import parser

File ~/../parser.py:15, in <module>
     13     from . import _parser
     14 else:
---> 15     import _parser
     17 try:
     18     import builtins as __builtin__

ImportError: /home/../_parser.so: undefined symbol: _Z8myVectorRNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE

CodePudding user response:

The function definition should be between %{ and %}. Everything between %{/%} is included directly in the generated wrapper. The function prototype should be at the end of the file after the %template declarations to direct SWIG to generate a wrapper for that function.

Since the function body is in the wrong place it isn't defined hence the undefined symbol error.

Stripped down example:

test.i

%module test

%{
#include <vector>

std::vector<std::vector<double>> myVector()
{
    return {{1.0,1.5},{2.0,2.5}};
}
%}

%include <std_vector.i>

%template(doubleVector) std::vector<double>;
%template(doubleVecVector) std::vector<std::vector<double>>;

std::vector<std::vector<double>> myVector();

Demo:

>>> import test
>>> test.myVector()
((1.0, 1.5), (2.0, 2.5))
  • Related