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.