0

I created this matrix.cpp class where I overloaded some operators:

template <typename T>
class MagicObject {
private:
    std::vector<std::vector<T> > mat;
    unsigned rows;
    unsigned cols;

public:
    MagicObject(unsigned _rows, unsigned _cols, const T& _initial);
    MagicObject(const MagicObject<T>& rhs);
    MagicObject();
    ~MagicObject();

    // Operator overloading, for "standard" mathematical MagicObject operations
    MagicObject<T>& operator=(const MagicObject<T>& rhs);

    // MagicObject mathematical operations
    MagicObject<T> operator+(const MagicObject<T>& rhs);
    MagicObject<T>& operator+=(const MagicObject<T>& rhs);
    MagicObject<T> operator-(const MagicObject<T>& rhs);
    MagicObject<T>& operator-=(const MagicObject<T>& rhs);
    MagicObject<T> operator*(const MagicObject<T>& rhs);
    MagicObject<T>& operator*=(const MagicObject<T>& rhs);
    MagicObject<T> transpose();

    // matrix/scalar operations
    MagicObject<T> operator+(const T& rhs);
    MagicObject<T> operator-(const T& rhs);
    MagicObject<T> operator*(const T& rhs);
    MagicObject<T> operator/(const T& rhs);

    // matrix/vector operations
    std::vector<T> operator*(const std::vector<T>& rhs);
    std::vector<T> diag_vec();

    // Access the individual elements
    T& operator()(const unsigned& row, const unsigned& col);
    const T& operator()(const unsigned& row, const unsigned& col) const;

    T& operator[](const unsigned &i);

    // Access the row and column sizes
    unsigned get_rows() const;
    unsigned get_cols() const;

    void _print();
};

I avoid to put the matrix.hpp because it is very long. In any case, the header contains the implementation that works correctly (in C++ of course). Now I want to use SWIG for creating a python module. To do so, I created this SWIG interface called matrix.i:

%module matrix
%{
#include "matrix.hpp"
%}

%include "matrix.hpp"

// used for the operator[]
%extend MagicObject<T> {
    T& __getitem__(unsigned int i) {
        return $self[i];
     }
}

// used for _print() function
%extend MagicObject<T> {
    void __print__() {
        print $self;
     }
}

%template(intMagicObject) MagicObject<int>;
%template(floatMagicObject) MagicObject<float>;
%template(doubleMagicObject) MagicObject<double>;

I use these commands to create the module:

swig -c++ -python matrix.i
g++ -O2 -fPIC -c matrix.cpp
g++ -O2 -fPIC -c matrix_wrap.cxx -I/Users/dado/anaconda/include/python2.7
g++ -lpython -dynamclib matrix.o matrix_wrap.o -o _matrix.so

and I obtain these errors when I execute the last command:

clang: warning: argument unused during compilation: '-dynamclib'
Undefined symbols for architecture x86_64:
  "MagicObject<double>::MagicObject()", referenced from:
      _wrap_new_doubleMagicObject(_object*, _object*) in matrix_wrap.o
      _wrap_doubleMagicObject_transpose(_object*, _object*) in matrix_wrap.o
      _wrap_doubleMagicObject___add__(_object*, _object*) in matrix_wrap.o
      _wrap_doubleMagicObject___sub__(_object*, _object*) in matrix_wrap.o
      _wrap_doubleMagicObject___div__(_object*, _object*) in matrix_wrap.o
      _wrap_doubleMagicObject___mul__(_object*, _object*) in matrix_wrap.o
  "MagicObject<float>::MagicObject()", referenced from:
      _wrap_new_floatMagicObject(_object*, _object*) in matrix_wrap.o
      _wrap_floatMagicObject_transpose(_object*, _object*) in matrix_wrap.o
      _wrap_floatMagicObject___add__(_object*, _object*) in matrix_wrap.o
      _wrap_floatMagicObject___sub__(_object*, _object*) in matrix_wrap.o
      _wrap_floatMagicObject___div__(_object*, _object*) in matrix_wrap.o
      _wrap_floatMagicObject___mul__(_object*, _object*) in matrix_wrap.o
  "MagicObject<int>::MagicObject()", referenced from:
      _wrap_new_intMagicObject(_object*, _object*) in matrix_wrap.o
      _wrap_intMagicObject_transpose(_object*, _object*) in matrix_wrap.o
      _wrap_intMagicObject___add__(_object*, _object*) in matrix_wrap.o
      _wrap_intMagicObject___sub__(_object*, _object*) in matrix_wrap.o
      _wrap_intMagicObject___div__(_object*, _object*) in matrix_wrap.o
      _wrap_intMagicObject___mul__(_object*, _object*) in matrix_wrap.o
  "_main", referenced from:
     implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

How do I solve this ? Thanks

EDIT Here my matrix.cpp file (just a snippet):

#include "matrix.hpp"
#include <iostream>

// Parameter Constructor
template<typename T>
MagicObject<T>::MagicObject(unsigned _rows, unsigned _cols, const T& _initial) {
    mat.resize(_rows);
    for (unsigned i=0; i<mat.size(); i++) {
        mat[i].resize(_cols, _initial);
    }
    rows = _rows;
    cols = _cols;
}

// Copy Constructor
template<typename T>
MagicObject<T>::MagicObject(const MagicObject<T>& rhs) {
    mat = rhs.mat;
    rows = rhs.get_rows();
    cols = rhs.get_cols();
}

// (Virtual) Destructor
template<typename T>
MagicObject<T>::~MagicObject() {}

// Assignment Operator
template<typename T>
MagicObject<T>& MagicObject<T>::operator=(const MagicObject<T>& rhs) {
    if (&rhs == this)
        return *this;

    unsigned new_rows = rhs.get_rows();
    unsigned new_cols = rhs.get_cols();

    // ..... rest here
spaghettifunk
  • 1,936
  • 4
  • 24
  • 46
  • The linker error you showed looked exactly like you didn't instantiated the templates in C++ properly anywhere in your library, but since you didnt reduce the question to the minmial complete example I cant analyse further, but probably you simply haven't given a *definition* of the default constructor and haven't spotted it so far. See http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file – Flexo Nov 19 '15 at 21:04
  • `print $self` in the %extend is also wrong and should fail long before it gets to the linker error with a syntax error. – Flexo Nov 19 '15 at 21:05
  • @Flexo Sorry, I don't really understand what you mean. I edited the post, maybe you can give me an example about it. – spaghettifunk Nov 24 '15 at 15:58
  • I'm guessing you don't define `MagicObject::MagicObject` anywhere in matrix.hpp. Either don't declare it or provide a definition some where appropriate. – Flexo Nov 24 '15 at 16:16

1 Answers1

0

You need to instantiate your template class in your .cpp or .h file, just like,

template class yourclass< double >;
Jack
  • 1
  • 3