ftylitak / qzxing

Qt/QML wrapper library for the ZXing library. 1D/2D barcode image processing library
Apache License 2.0
617 stars 340 forks source link

How to use as static library? #79

Open TheSDTM opened 6 years ago

TheSDTM commented 6 years ago

Hello. How to use it with QT as a static library?

I have compiled it with CONFIG += staticlib qzxing_multimedia Next I have included it in .pro file this way:

CONFIG += v-play qzxing_multimedia
include(QZXing/QZXing.pri)
LIBS += -L"$$_PRO_FILE_PWD_/libs/" -lQZXingDesktop

Where I had removed in QZXing.pri all SOURCES += (just to include headers and defines).

But it returns

Undefined symbols for architecture x86_64:
  "ImageHandler::save(QObject*, QString const&, int, int, int, int)", referenced from:
      ImageHandler::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) in moc_ImageHandler.o
  "QZXingFilter::createFilterRunnable()", referenced from:
      vtable for QZXingFilter in moc_QZXingFilter.o
  "QZXingFilter::handleDecodingStarted()", referenced from:
      QZXingFilter::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) in moc_QZXingFilter.o
  "QZXingFilter::handleDecodingFinished(bool)", referenced from:
      QZXingFilter::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) in moc_QZXingFilter.o
  "QZXingFilter::~QZXingFilter()", referenced from:
      vtable for QZXingFilter in moc_QZXingFilter.o
  "QZXingFilter::~QZXingFilter()", referenced from:
      vtable for QZXingFilter in moc_QZXingFilter.o
  "QZXingFilterRunnable::run(QVideoFrame*, QVideoSurfaceFormat const&, QFlags<QVideoFilterRunnable::RunFlag>)", referenced from:
      vtable for QZXingFilterRunnable in moc_QZXingFilter.o
  "QZXingFilterRunnable::~QZXingFilterRunnable()", referenced from:
      vtable for QZXingFilterRunnable in moc_QZXingFilter.o
  "QZXingFilterRunnable::~QZXingFilterRunnable()", referenced from:
      vtable for QZXingFilterRunnable in moc_QZXingFilter.o
  "QZXing::encodeData(QString const&, QZXing::EncoderFormat, QSize, QZXing::EncodeErrorCorrectionLevel)", referenced from:
      QZXing::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) in moc_QZXing.o
  "QZXing::setDecoder(unsigned int const&)", referenced from:
      QZXing::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) in moc_QZXing.o
  "QZXing::decodeImage(QImage const&, int, int, bool)", referenced from:
      QZXing::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) in moc_QZXing.o
  "QZXing::getTryHarder()", referenced from:
      QZXing::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) in moc_QZXing.o
  "QZXing::setTryHarder(bool)", referenced from:
      QZXing::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) in moc_QZXing.o
  "QZXing::decodeImageQML(QObject*)", referenced from:
      QZXing::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) in moc_QZXing.o
  "QZXing::decodeImageQML(QUrl const&)", referenced from:
      QZXing::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) in moc_QZXing.o
  "QZXing::registerQMLTypes()", referenced from:
      _main in main.o
      _main in main.o
  "QZXing::decodeSubImageQML(QObject*, int, int, int, int)", referenced from:
      QZXing::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) in moc_QZXing.o
  "QZXing::decodeSubImageQML(QUrl const&, int, int, int, int)", referenced from:
      QZXing::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) in moc_QZXing.o
  "QZXing::decodeImageFromFile(QString const&, int, int, bool)", referenced from:
      QZXing::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) in moc_QZXing.o
  "QZXing::registerQMLImageProvider(QQmlEngine&)", referenced from:
      _main in main.o
      _main in main.o
  "QZXing::getProcessTimeOfLastDecoding()", referenced from:
      QZXing::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) in moc_QZXing.o
  "QZXing::~QZXing()", referenced from:
      vtable for QZXing in moc_QZXing.o
  "QZXing::~QZXing()", referenced from:
      vtable for QZXing in moc_QZXing.o
  "QZXing::foundedFormat() const", referenced from:
      QZXing::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) in moc_QZXing.o
  "QZXing::getEnabledFormats() const", referenced from:
      QZXing::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) in moc_QZXing.o
  "QZXing::charSet() const", referenced from:
      QZXing::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) in moc_QZXing.o
  "non-virtual thunk to QZXingFilterRunnable::run(QVideoFrame*, QVideoSurfaceFormat const&, QFlags<QVideoFilterRunnable::RunFlag>)", referenced from:
      vtable for QZXingFilterRunnable in moc_QZXingFilter.o
  "non-virtual thunk to QZXingFilterRunnable::~QZXingFilterRunnable()", referenced from:
      vtable for QZXingFilterRunnable in moc_QZXingFilter.o
  "non-virtual thunk to QZXingFilterRunnable::~QZXingFilterRunnable()", referenced from:
      vtable for QZXingFilterRunnable in moc_QZXingFilter.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Could you help me?

ftylitak commented 6 years ago

Hello @TheSDTM

through your logs I understand you have properly setup the project since your target project is able to detect and use the .a static library file.

The issue lies in the content of the .a file itself. During your trials to make the above work, you commented out the source files from the QZXing project. This edited version of QZXing.pri is perfect for the final project, though, somewhere along the way you compiled by mistake also the QZXing project with it. This resulted to a relatively "small" .a file without generating any compilation error so it passed by unnoticed.

I believe that if you restore the commented parts of QZXing.pri and rebuild QZXing.pro you will get a much bigger .a file as result.

Do you confirm?

From my side I keep a note to update the QZXing.pri to handle the deactivation of the source files with a more elegant way.

TheSDTM commented 6 years ago

Thank you, but I cloned repository, then compiled as static library, and only after compilation I removed cpp files from .pro file. What’s is regular size of .a file compiled for desktop?

ftylitak commented 6 years ago

When i compile QZXing with "qzxing_multimedia" for MinGW32 in Windows 10 in Debug mode I get a .a file of approximately 20MB.

I believe i know why you get these errors. In the QZXing.pro file, upon cloning it from the repository, its first line (after the licensing comments) is to include the QZXing.pri. By the time a .pri gets included, the .pro file must have already stated what CONFIG flags to use. In order to properly add the configuration for qzxing_multimedia, you need to add the following line as the first line in the QZXing.pro file.

So, instead of:

include(QZXing.pri)

VERSION = 2.3

TARGET = QZXing
TEMPLATE = lib

#CONFIG += staticlib

you should use:

CONFIG += qzxing_multimedia

include(QZXing.pri)

VERSION = 2.3

TARGET = QZXing
TEMPLATE = lib

CONFIG += staticlib
TheSDTM commented 6 years ago

Yes, I have added multimedia to configure before including .pri. For now I am receiving no member named registerQMLTypes and registerQMLImageProvider. I guess that they are included only with qzxing_multimedia. But it doesn’t included despite I added it to config

ftylitak commented 6 years ago

This sounds different from your initial issue, correct? Your initial issue was linker error though the "no member named <>" is compile error.
Would you like to share some compilation logs?

I would like to go back to your initial decision of using the project as static library. Wouldn't it be easier to just add the .pri to your project and just use it through the source code? Have you tried it? Does it work?

TheSDTM commented 6 years ago

This sounds different from your initial issue, correct?

Yes. In my first issue I removed all #ifdef tags in code that corresponds to not adding registerQMLTypes and registerQMLImageProvider to header file.

Would you like to share some compilation logs?

Here it is:

10:52:43: Running steps for project Tehnoparkapp...
10:52:43: Configuration unchanged, skipping qmake step.
10:52:43: Starting: "/usr/bin/make" 
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang++ -c -pipe -stdlib=libc++ -g -std=gnu++11  -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk -mmacosx-version-min=10.10 -Wall -W -fPIC -DENABLE_QR -DQT_QML_DEBUG -DQT_QUICK_LIB -DQT_WIDGETS_LIB -DQT_MULTIMEDIA_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_WEBSOCKETS_LIB -DQT_NETWORK_LIB -DQT_SQL_LIB -DQT_CORE_LIB -I../tehnoparkapp -I. -I../tehnoparkapp/vendor/QZXing -I../../V-PlaySDK/V-Play/clang_64/include/VPlay -I../../V-PlaySDK/V-Play/clang_64/lib/QtQuick.framework/Headers -I../../V-PlaySDK/V-Play/clang_64/lib/QtWidgets.framework/Headers -I../../V-PlaySDK/V-Play/clang_64/lib/QtMultimedia.framework/Headers -I../../V-PlaySDK/V-Play/clang_64/lib/QtGui.framework/Headers -I../../V-PlaySDK/V-Play/clang_64/lib/QtQml.framework/Headers -I../../V-PlaySDK/V-Play/clang_64/lib/QtWebSockets.framework/Headers -I../../V-PlaySDK/V-Play/clang_64/lib/QtNetwork.framework/Headers -I../../V-PlaySDK/V-Play/clang_64/lib/QtSql.framework/Headers -I../../V-PlaySDK/V-Play/clang_64/lib/QtCore.framework/Headers -I. -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/System/Library/Frameworks/OpenGL.framework/Headers -I/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/System/Library/Frameworks/AGL.framework/Headers -I../../V-PlaySDK/V-Play/clang_64/mkspecs/macx-clang -F/Users/yaroslav/V-PlaySDK/V-Play/clang_64/lib -o main.o ../tehnoparkapp/main.cpp
../tehnoparkapp/main.cpp:45:13: error: no member named 'registerQMLTypes' in 'QZXing'
    QZXing::registerQMLTypes();
    ~~~~~~~~^
../tehnoparkapp/main.cpp:46:13: error: no type named 'registerQMLImageProvider' in 'QZXing'
    QZXing::registerQMLImageProvider(engine);
    ~~~~~~~~^
2 errors generated.
make: *** [main.o] Error 1
10:52:44: The process "/usr/bin/make" exited with code 2.
Error while building/deploying project Tehnoparkapp (kit: V-Play Desktop (Qt 5.10.1 clang))
When executing step "Make"
10:52:45: Elapsed time: 00:02.

I would like to go back to your initial decision of using the project as static library. Wouldn't it be easier to just add the .pri to your project and just use it through the source code? Have you tried it? Does it work?

Yes, it works. I would be easier, however due to bug in Xcode, MacOS (or somewhere else) I am not able to run iOS app again after compilation. I am able to run it only once after compilation. And in order to run it I need to recompile whole project.

I was able to fix all issues by adding #define QZXING_QML to QZXing.h file. The issue was simple. Everything was good with static libraries, but included header files doesn't contain this functions unless __#define QZXING_QML__ added.

grafit7 commented 6 years ago

https://github.com/EDDragonWolf/QZXingBinaries

Thaodan commented 5 years ago

I'm having the same issue with static builds (using pri) for android.