0

I have some Qt C++ code I would like to make a python extension for. The module is being created with no error, however, when I try importing it in python I get an ImportError

I googled the problem and apparently it's an issue linking the proper libraries, however, I've already tried linking all the Qt5 libraries.

Here is the header file of the code I am trying to wrap, token.h:

#ifndef TOKEN_H
#define TOKEN_H

#include <QVector>
#include <QString>

class Token {
private:
    QString name;
    int ID;

    //The pixel locations of the bounds of the bounding box
    //of the token.
    int top, bottom, left, right;

public:
    //Pointers to the tokens (shapes and letters) that are
    //direct children of the current token (i.e. not nested
    //within yet another token).
    QVector<Token *> childTokens;

    Token();
    ~Token();
    void setName(const QString &);
    void setID(int);
    void setBounds(int, int, int, int);
    void addChild(Token *);
    void addChildVector(QVector<Token *>);

    int getTop();
    int getBottom();
    int getLeft();
    int getRight();
    int getID();

    QString getName();
};

#endif // TOKEN_H

token.cpp

#include "token.h"

Token::Token() {
    top = 0;
    bottom = 0;
    left = 0;
    right = 0;
}

Token::~Token() {
    for(int i = 0; i < childTokens.size(); ++i) {
        delete childTokens[i];
    }
}

void Token::setName(const QString & nameVal) {
    name = nameVal;
}

void Token::setID(int IDVal) {
    ID = IDVal;
}

void Token::setBounds(int topVal, int bottomVal, int leftVal, int rightVal) {
    top = topVal;
    bottom = bottomVal;
    left = leftVal;
    right = rightVal;
}

void Token::addChild(Token * childToken) {
    childTokens.append(childToken);
}

void Token::addChildVector(QVector<Token *> childTokenVec) {
    for(int i = 0; i < childTokenVec.size(); ++i) {
        addChild(childTokenVec[i]);
    }
}

int Token::getTop() {
    return top;
}

int Token::getBottom() {
    return bottom;
}

int Token::getLeft() {
    return left;
}

int Token::getRight() {
    return right;
}

int Token::getID() {
    return ID;
}

QString Token::getName() {
    return name;
}

Here is the interface file, token.i

%module token

%{
#define SWIG_FILE_WITH_INIT
#include "token.h"
%}

%include "token.h"

Here are the commands I run to create the python module token

swig -python -c++ token.i

g++ -c -fpic token_wrap.cxx -I/usr/include/python3.6m -I/usr/include/x86_64-linux-gnu/qt5/QtGui -I/usr/include/x86_64-linux-gnu/qt5/QtCore -I/usr/include/x86_64-linux-gnu/qt5/

g++ -L/usr/lib/x86_64-linux-gnu -lQt5Core -lQt5Gui -lQt5Concurrent -lQt5Xml -lQt5XcbQpa -lQt5Widgets -lQt5Test -lQt5Sql -lQt5PrintSupport -lQt5OpenGL -lQt5Network -lQt5EglFSDeviceIntegration -lQt5EglFsKmsSupport -lQt5DBus  -shared token_wrap.o -o _token.so

So the commands seem to run with no issue, but here is the error message upon attempting to import

python3
Python 3.6.8 (default, Jan 14 2019, 11:02:34) 
[GCC 8.0.1 20180414 (experimental) [trunk revision 259383]] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import token
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/danny/Desktop/sketch2code/Qt Project Files/token.py", line 15, in <module>
    import _token
ImportError: /home/danny/Desktop/sketch2code/Qt Project Files/_token.so: undefined symbol: _ZN10QArrayData11shared_nullE
Error in sys.excepthook:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/apport_python_hook.py", line 62, in apport_excepthook
    import re, traceback
  File "/usr/lib/python3.6/traceback.py", line 5, in <module>
    import linecache
  File "/usr/lib/python3.6/linecache.py", line 11, in <module>
    import tokenize
  File "/usr/lib/python3.6/tokenize.py", line 35, in <module>
    from token import *
  File "/home/danny/Desktop/sketch2code/Qt Project Files/token.py", line 15, in <module>
    import _token
ImportError: /home/danny/Desktop/sketch2code/Qt Project Files/_token.so: undefined symbol: _ZN10QArrayData11shared_nullE

Original exception was:
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/danny/Desktop/sketch2code/Qt Project Files/token.py", line 15, in <module>
    import _token
ImportError: /home/danny/Desktop/sketch2code/Qt Project Files/_token.so: undefined symbol: _ZN10QArrayData11shared_nullE
>>> exit()

EDIT: Possible Solution If SWIG is not a Must

I wasn't able to get this working with SWIG, although I'm certain there is a way to get it to work. Anyway, I'm adding this in case someone with my same question stumbles on this post.

I ended up using a more powerful tool for creating python bindings for Qt, Shiboken. It is able to create bindings for Qt slots and signals.

Here is a very helpful tutorial: Using Shiboken2 to create Python bindings for a Qt library And here is the full documentation: Shiboken the Binding Generator

Although one quirk that I faced was that I needed to change the name of the Token class. At least when using the python3 interpreter, the class name Token gave me issues that were resolved by simply changing the class name. Other than that Shiboken was lovely and a pleasure to use.

Danny Ibrahim
  • 87
  • 1
  • 12
  • It seems to me that you are using a wrong version QtCore or a mismatch. The version that your program expects is different from the version, which is found by Python. Try to make a simple executable first and see if this works. If okay, proceed and ensure Python loads the right `.so` – Jens Munk Jul 22 '19 at 18:16
  • Does using this to link instead: `g++ -shared token_wrap.o -o _token.so -L/usr/lib/x86_64-linux-gnu -lQt5Core -lQt5Gui -lQt5Concurrent -lQt5Xml -lQt5XcbQpa -lQt5Widgets -lQt5Test -lQt5Sql -lQt5PrintSupport -lQt5OpenGL -lQt5Network -lQt5EglFSDeviceIntegration -lQt5EglFsKmsSupport -lQt5DBus` fix it? I'd guess you're seeing this: https://stackoverflow.com/a/8140599/168175 – Flexo Jul 22 '19 at 19:08
  • @JensMunk So the code runs in Qt creator fine, and Qt5 is the only version of Qt I have installed if that's what you mean. – Danny Ibrahim Jul 22 '19 at 21:32
  • @Flexo No, unfortunately, it didn't fix it, still the same error message. Thanks for the suggestion though. – Danny Ibrahim Jul 22 '19 at 21:38
  • I have seen the same error when a wrong version of Qt was loaded. If you can supply a full example, I can see if I can make it work – Jens Munk Jul 22 '19 at 23:42
  • @JensMunk I've added the toke.cpp file just now, is there anything else you might need? The Qt version I am using is 5.12.4 – Danny Ibrahim Jul 23 '19 at 20:49
  • No, I will make it work tomorrow - time is 11 pm here... Till later – Jens Munk Jul 23 '19 at 20:53
  • Unfortunately, I never figured out how to fix this, but in case anyone stumbles on this page with the same question, I ended up using shiboken, which is a much more powerful tool (at least for Qt) able to wrap Qt slots and signals. I'll edit the question and add a few links. – Danny Ibrahim Jul 26 '19 at 22:22

0 Answers0