"ImportError: undefined symbols" but It seems I defined

  c++, makefile, pybind11, python-3.x

I have a makefile for compiling a shared library to use a bunch of c++ classes in python.

Makefile

RBASIC_CPP=src/Friedrich/Rubix/RxBasic.cpp
RBASIC_O=obj/RxBasic.o

RCUBE_CPP=src/Friedrich/Rubix/RCube.cpp
RCUBE_O=obj/RCube.o

RXUTILITY_CPP=src/Friedrich/Rubix/RxXUtility.cpp
RXUTILITY_O=obj/RxXUtility.o

RUTILITY_CPP=src/Friedrich/Rubix/RxUtility.cpp
RUTILITY_O=obj/RxUtility.o

RUBIX_O=obj/Rubix.o

FACE_CPP=src/Friedrich/FFace.cpp
FACE_O=obj/FFace.o

CUBE_CPP=src/Friedrich/FCube.cpp
CUBE_O=obj/FCube.o

PHASE_CPP=src/Friedrich/FPhase.cpp
PHASE_O=obj/FPhase.o

CROSS_CPP=src/Friedrich/FCross.cpp
CROSS_O=obj/FCross.o

F2L_CPP=src/Friedrich/FF2L.cpp
F2L_O=obj/FF2L.o

OLL_CPP=src/Friedrich/FOLL.cpp
OLL_O=obj/FOLL.o

PLL_CPP=src/Friedrich/FPLL.cpp
PLL_O=obj/FPLL.o

PYF_CPP=src/PyFriedrich.cpp
PYF_O=obj/PyFriedrich.o

FINAL_TARGET=release/PyFriedrich.cpython-38-x86_64-linux-gnu.so

PYBIND11_PATH=/home/kubuntu/.local/lib/python3.8/site-packages/pybind11/include
CPYTHON_PATH=/usr/include/python3.8

CPPSTD=c++14

$(FINAL_TARGET): $(RUTILITY_O) $(RXUTILITY_O) $(RCUBE_O) $(RBASIC_O) $(FACE_O) $(CUBE_O) $(PHASE_O) $(CROSS_O) $(F2L_O) $(OLL_O) $(PLL_O) $(PYF_O)
    g++ -O3 -Wall -shared -std=$(CPPSTD) -fPIC $(RUTILITY_O) $(RXUTILITY_O) $(RCUBE_O) $(FACE_O) $(CUBE_O) $(PHASE_O) $(CROSS_O) $(F2L_O) $(OLL_O) $(PLL_O) $(PYF_O) $(RBASIC_O) -o $(FINAL_TARGET) 

$(RBASIC_O) : $(RBASIC_CPP)
    g++ -std=$(CPPSTD) -fPIC -c -o $(RBASIC_O) $(RBASIC_CPP)
    
$(RCUBE_O) : $(RCUBE_CPP)
    g++ -std=$(CPPSTD) -fPIC -c -o $(RCUBE_O) $(RCUBE_CPP)

$(RXUTILITY_O) : $(RXUTILITY_CPP)
    g++ -std=$(CPPSTD) -fPIC -c -o $(RXUTILITY_O) $(RXUTILITY_CPP)

$(RUTILITY_O) : $(RUTILITY_CPP)
    g++ -std=$(CPPSTD) -fPIC -c -o $(RUTILITY_O) $(RUTILITY_CPP)

$(FACE_O): $(FACE_CPP)
    g++ -std=$(CPPSTD) -fPIC -c -o $(FACE_O) $(FACE_CPP)
    
$(CUBE_O): $(CUBE_CPP)
    g++ -std=$(CPPSTD) -fPIC -c -o $(CUBE_O) $(CUBE_CPP)
    
$(PHASE_O): $(PHASE_CPP)
    g++ -std=$(CPPSTD) -fPIC -c -o $(PHASE_O) $(PHASE_CPP)
    
$(CROSS_O): $(CROSS_CPP)
    g++ -std=$(CPPSTD) -fPIC -c -o $(CROSS_O) $(CROSS_CPP)
    
$(F2L_O): $(F2L_CPP)
    g++ -std=$(CPPSTD) -fPIC -c -o $(F2L_O) $(F2L_CPP)
    
$(OLL_O): $(OLL_CPP)
    g++ -std=$(CPPSTD) -fPIC -c -o $(OLL_O) $(OLL_CPP)
    
$(PLL_O): $(PLL_CPP)
    g++ -std=$(CPPSTD) -fPIC -c -o $(PLL_O) $(PLL_CPP)
    
$(PYF_O): $(PYF_CPP)
    g++ -std=$(CPPSTD) -I$(CPYTHON_PATH) -I$(PYBIND11_PATH) -fPIC -c -o $(PYF_O) $(PYF_CPP)

It compiles fine, but when I try to import the module in python I got the following error:

>>> import PyFriedrich as f
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: /home/kubuntu/Desktop/python3/PyFriedrich/release/PyFriedrich.cpython-38-x86_64-linux-gnu.so: undefined symbol: _ZN3rbx10RAlgorithmC1EPKc

rbx::RAlgorithm is a struct that I declared in RxBasic.h and which functions are defined in RxBasic.cpp, I used these two files to create another python module and it works

RxBasic.h

#pragma once

#ifdef _MSC_VER
    #pragma warning( disable : 4305 )
#endif //_MSC_VER

//CPP-LIB
#include<iostream>
#include<vector>
#include<array>

//OWN-LIB
#include "RxCore.h"

_RUBIX_BEGIN

struct RColorTag {
    flag_t operator()(const flag_t&);
};

struct RPositionTag {
    flag_t operator()(const flag_t&);
};

struct RDirectionTag {
    flag_t operator()(const flag_t&);
};

template<class _Tag>
struct RElement {

private:

    using _MyTemp = RElement<_Tag>;

public:

    RElement() : _Val(__null__) {}

    RElement(const flag_t& flag) : _Val(_Tag()(flag)) {}

    RElement(const _MyTemp& other) : _Val(other._Val) {}

    RElement(_MyTemp&& other) : _Val(other._Val) { other._Val = __null__; }

    _MyTemp& operator=(const _MyTemp& other) {
        _Val = other._Val;
        return *this;
    }

    _MyTemp& operator=(_MyTemp&& other) {
        _Val = other._Val;
        other._Val = __null__;
        return *this;
    }

    bool operator==(const _MyTemp& other) const {
        return _Val == other._Val;
    }

    bool operator!=(const _MyTemp& other) const {
        return _Val != other._Val;
    }

    friend std::ostream& operator<<(std::ostream& out, const _MyTemp& _Elem) {
        return out << _Elem._Val;
    }

    friend std::istream& operator>>(std::istream& in, _MyTemp& _Elem) {
        return in >> _Elem._Val;
    }

    operator flag_t() const {
        return _Val;
    }

    operator bool() const {
        return _Val != __null__;
    }

private:

    flag_t _Val;

};

using RColor     = RElement<RColorTag>;

const RColor NULL_COLOR(__null__);
const RColor YELLOW(__yellow__);
const RColor RED(__red__);
const RColor GREEN(__green__);
const RColor ORANGE(__orange__);
const RColor BLUE(__blue__);
const RColor WHITE(__white__);

using RPosition  = RElement<RPositionTag>;

const RPosition NULL_POSITION(__null__);
const RPosition UP(__up__);
const RPosition FRONT(__front__);
const RPosition RIGHT(__right__);
const RPosition BACK(__back__);
const RPosition LEFT(__left__);
const RPosition DOWN(__down__);

using RDirection = RElement<RDirectionTag>;

const RDirection NULL_DIRECTION(__null__);
const RDirection CLK(__clk__);
const RDirection CTR(__ctr__);
const RDirection DBL(__dbl__);

struct RFacelet {
    RFacelet() noexcept;
    RFacelet(const RColor&, const RPosition&) noexcept;
    RFacelet(const RFacelet&) noexcept;
    RFacelet(RFacelet&&) noexcept;
    RColor color;
    RPosition position;
    RFacelet& operator=(const RFacelet& other) noexcept;
    RFacelet& operator=(RFacelet&& other) noexcept;
    RFacelet& operator=(const RColor&) noexcept;
    bool operator==(const RFacelet&) const noexcept;
    bool operator!=(const RFacelet&) const noexcept;
    operator bool() const noexcept;
};

const RFacelet NULL_FACELET;

struct RCorner {
    RCorner() noexcept;
    RCorner(const RFacelet&, const RFacelet&, const RFacelet&) noexcept;
    RCorner(const RCorner&) noexcept;
    RCorner(RCorner&&) noexcept;
    RFacelet first, second, third;
    RCorner& operator=(const RCorner& other) noexcept;
    RCorner& operator=(RCorner&& other) noexcept;
    bool operator==(const RCorner& other) noexcept;
    bool operator!=(const RCorner& other) noexcept;
    operator bool() const noexcept;
    //               +++++++++++++++++ 
    //            ++             ++  +  
    //         ++   first    ++      +
    //      ++           ++          +
    //   +++++++++++++++             +
    //   +             +   second    +
    //   +             +           ++
    //   +   third     +        ++
    //   +             +     ++ 
    //   +             +  ++
    //   +++++++++++++++ 

};

struct REdge {
    REdge() noexcept;
    REdge(const RFacelet&, const RFacelet&) noexcept;
    REdge(const REdge&) noexcept;
    REdge(REdge&&) noexcept;
    RFacelet first, second;
    REdge& operator=(const REdge& other) noexcept;
    REdge& operator=(REdge&& other) noexcept;
    bool operator==(const REdge& other) noexcept;
    bool operator!=(const REdge& other) noexcept;
    operator bool() const noexcept;
};

struct RMove {
    RMove() noexcept;
    RMove(const RPosition&, const RDirection&) noexcept;
    RMove(const RMove&) noexcept;
    RMove(RMove&&) noexcept;
    RPosition position;
    RDirection direction;
    RMove& operator=(const RMove& other) noexcept;
    RMove& operator=(RMove&& other) noexcept;
    bool operator==(const RMove& other) noexcept;
    bool operator!=(const RMove& other) noexcept;
    operator bool() const noexcept;
    friend std::ostream& operator<<(std::ostream& out, const RMove& RM);
    operator std::string() const noexcept;
};

//AVAILABLE MOVES
const RMove NULL_MOVE = { NULL_POSITION, NULL_DIRECTION };
const RMove UP_CLK = { UP, CLK };
const RMove UP_CTR = { UP, CTR };
const RMove UP_DBL = { UP, DBL };
const RMove FRONT_CLK = { FRONT, CLK };
const RMove FRONT_CTR = { FRONT, CTR };
const RMove FRONT_DBL = { FRONT, DBL };
const RMove RIGHT_CLK = { RIGHT, CLK };
const RMove RIGHT_CTR = { RIGHT, CTR };
const RMove RIGHT_DBL = { RIGHT, DBL };
const RMove BACK_CLK = { BACK, CLK };
const RMove BACK_CTR = { BACK, CTR };
const RMove BACK_DBL = { BACK, DBL };
const RMove LEFT_CLK = { LEFT, CLK };
const RMove LEFT_CTR = { LEFT, CTR };
const RMove LEFT_DBL = { LEFT, DBL };
const RMove DOWN_CLK = { DOWN, CLK };
const RMove DOWN_CTR = { DOWN, CTR };
const RMove DOWN_DBL = { DOWN, DBL };

const std::array<RMove, 19> available_moves = {
    NULL_MOVE,
    UP_CLK,
    UP_CTR,
    UP_DBL,
    FRONT_CLK,
    FRONT_CTR,
    FRONT_DBL,
    RIGHT_CLK,
    RIGHT_CTR,
    RIGHT_DBL,
    BACK_CLK,
    BACK_CTR,
    BACK_DBL,
    LEFT_CLK,
    LEFT_CTR,
    LEFT_DBL,
    DOWN_CLK,
    DOWN_CTR,
    DOWN_DBL
};

struct RAlgorithm : std::vector<RMove> {

    RAlgorithm();

    explicit RAlgorithm(const std::string&);

    RAlgorithm& operator+=(const RAlgorithm&);

    explicit operator std::string() const noexcept {
        std::string result;
        for (auto it = begin(); it != end(); ++it) {
            if (*it) {
                result += char(it->position);
                result += char(it->direction);
                if (it->direction != CLK) {
                    result += ' ';
                }
            }
        }
        return result;
    }
};

template<size_t _Side>
constexpr size_t side_length = _Side;
template<size_t _Side>
constexpr size_t face_length = _Side * _Side;
template<size_t _Side>
constexpr size_t cube_length = _Side * _Side * 6;

_RUBIX_END

#ifdef _MSC_VER
    #pragma warning( default : 4305 )
#endif //_MSC_VER

RxBasic.cpp

#include "RxBasic.h"

_RUBIX_BEGIN

//RMove methods

flag_t RColorTag::operator()(const flag_t& flag) {
    return __get_color_flag(flag);
}

flag_t RPositionTag::operator()(const flag_t& flag) {
    return __get_position_flag(flag);
}

flag_t RDirectionTag::operator()(const flag_t& flag) {
    return __get_direction_flag(flag);
}

//RFacelet methods

RFacelet::RFacelet() noexcept :
    color(),
    position()
{}

RFacelet::RFacelet(const RColor& _Color, const RPosition& _Position) noexcept :
    color(_Color),
    position(_Position)
{}

RFacelet::RFacelet(const RFacelet& other) noexcept :
    color(other.color),
    position(other.position)
{}

RFacelet::RFacelet(RFacelet&& other) noexcept :
    color(std::move(other.color)),
    position(std::move(other.position))
{}

RFacelet& RFacelet::operator=(const RFacelet& other) noexcept {
    color     =  other.color;
    position  =  other.position;
    return *this;
}

RFacelet& RFacelet::operator=(RFacelet&& other) noexcept {
    color     =  std::move(other.color);
    position  =  std::move(other.position);
    return *this;
}

RFacelet& RFacelet::operator=(const RColor& _Color) noexcept {
    color = _Color;
    return *this;
}

bool RFacelet::operator==(const RFacelet& other) const noexcept {
    return color == other.color && position == other.position;
}

bool RFacelet::operator!=(const RFacelet& other) const noexcept {
    return color != other.color || position != other.position;
}

RFacelet::operator bool() const noexcept {
    return color && position;
}

//RubxiCorner methods

RCorner::RCorner() noexcept :
    first(),
    second(),
    third()
{}

RCorner::RCorner(const RFacelet& _First, const RFacelet& _Second, const RFacelet& _Third) noexcept :
    first(_First),
    second(_Second),
    third(_Third)
{}

RCorner::RCorner(const RCorner& other) noexcept :
    first(other.first),
    second(other.second),
    third(other.third)
{}

RCorner::RCorner(RCorner&& other) noexcept :
    first(std::move(other.first)),
    second(std::move(other.second)),
    third(std::move(other.third))
{}

RCorner& RCorner::operator=(const RCorner& other) noexcept {
    first   =  other.first;
    second  =  other.second;
    third   =  other.third;
    return *this;
}

RCorner& RCorner::operator=(RCorner&& other) noexcept {
    first   =  std::move(other.first);
    second  =  std::move(other.second);
    third   =  std::move(other.third);
    return *this;
}

bool RCorner::operator==(const RCorner& other) noexcept {
    return first == other.first && second == other.second && third == other.third;
}

bool RCorner::operator!=(const RCorner& other) noexcept {
    return first != other.first || second != other.second || third != other.third;
}

RCorner::operator bool() const noexcept {
    return first && second && third;
}

//REdge methods

REdge::REdge() noexcept :
    first(),
    second()
{}

REdge::REdge(const RFacelet& _First, const RFacelet& _Second) noexcept :
    first(_First),
    second(_Second)
{}

REdge::REdge(const REdge& other) noexcept :
    first(other.first),
    second(other.second)
{}

REdge::REdge(REdge&& other) noexcept :
    first(std::move(other.first)),
    second(std::move(other.second))
{}

REdge& REdge::operator=(const REdge& other) noexcept {
    first = other.first;
    second = other.second;
    return *this;
}

REdge& REdge::operator=(REdge&& other) noexcept {
    first = std::move(other.first);
    second = std::move(other.second);
    return *this;
}

bool REdge::operator==(const REdge& other) noexcept {
    return first == other.first && second == other.second;
}

bool REdge::operator!=(const REdge& other) noexcept {
    return first != other.first || second != other.second;
}

REdge::operator bool() const noexcept {
    return first && second;
}

//RMove methods

RMove::RMove() noexcept :
    position(),
    direction()
{}

RMove::RMove(const RPosition& pos, const RDirection& dir) noexcept :
    position(pos),
    direction(dir)
{}

RMove::RMove(const RMove& other) noexcept :
    position(other.position),
    direction(other.direction)
{}

RMove::RMove(RMove&& other) noexcept :
    position(std::move(other.position)),
    direction(std::move(other.direction))
{}

RMove& RMove::operator=(const RMove& other) noexcept {
    position = other.position;
    direction = other.direction;
    return *this;
}

RMove& RMove::operator=(RMove&& other) noexcept {
    position = std::move(other.position);
    direction = std::move(other.direction);
    return *this;
}

bool RMove::operator==(const RMove& other) noexcept {
    return position == other.position && direction == other.direction;
}

bool RMove::operator!=(const RMove& other) noexcept {
    return position != other.position || direction != other.direction;
}

RMove::operator bool() const noexcept {
    return position && direction;
}

RMove::operator std::string() const noexcept {
    return std::string(1, char(position)) + char(direction);
}

std::ostream& operator<<(std::ostream& out, const RMove& RM) {
    out << RM.position << RM.direction;
    return out;
}

//RAlgorithm methods

using _MyBase = std::vector<RMove>;

RAlgorithm::RAlgorithm() : _MyBase() {}

RAlgorithm::RAlgorithm(const std::string& alg) : _MyBase() {
    if (!alg.empty()) {
        RMove temp;
        for (auto it = alg.begin(); it != alg.end() - 1; ++it) {
            switch (*it) {
            case __up__:
            case __front__:
            case __right__:
            case __back__:
            case __left__:
            case __down__:
                switch (*(it + 1)) {
                case __clk__:
                case __ctr__:
                case __dbl__:
                    push_back({ RPosition(*it), RDirection(*(it + 1)) });
                default: continue;
                }
            default: continue;
            }
        }
    }
}

RAlgorithm& RAlgorithm::operator+=(const RAlgorithm& alg) {
    _MyBase::insert(_MyBase::end(), alg.begin(), alg.end());
    return *this;
}

_RUBIX_END

I posted anything I guess you need, if you will need something else just say me and I will post it

I guess to have done something wrong in the makefile but I’m not sure, does anyone can help me?

Source: Windows Questions C++

LEAVE A COMMENT