Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Virtual method in a DLL Shared Lib

Virtual method in a DLL Shared Lib

Scheduled Pinned Locked Moved General and Desktop
10 Posts 4 Posters 2.7k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    calak
    wrote on last edited by
    #1

    Hi everyone!

    I have a little problem that I can't resolve.
    I reproduced it in simplier's context to make it easy to understand.

    So, I try to compile some piece of code to build a SharedLib in Qt.
    This SharedLib is a tree of class (2 in this exemple), with an abstract base class and a concrete class.

    Here's files:

    main.cpp
    [code]
    #include <QCoreApplication>

    #include <string>
    #include <iostream>

    #include "SharedLib/Concrete.hpp"

    int main(int argc, char *argv[])
    {
    QCoreApplication a(argc, argv);

    std::cout << "HELLOOOOWWW\n";
    
    Test::SharedLibConcrete foo;
    foo.test();
    
    return a.exec&#40;&#41;;
    

    }[/code]

    Concrete.hpp
    [code]#ifndef SHAREDLIB_CONCRETE_HPP
    #define SHAREDLIB_CONCRETE_HPP

    #include <string>

    #include "SharedLib/global.hpp"
    #include "SharedLib/Abstract.hpp"

    namespace Test
    {

    class SHAREDLIB_EXPORT SharedLibConcrete : public SharedLibAbstract
    {

    public:
        SharedLibConcrete() : SharedLibAbstract() {
        }
        ~SharedLibConcrete() = default;
    
        std::string init() {
          return std::string("Yeah, that's ruleZ!");
        }
    

    };

    } // namespace Test

    #endif // SHAREDLIB_CONCRETE_HPP[/code]

    Abstract.hpp
    [code]#ifndef SHAREDLIB_ABSTRACT_HPP
    #define SHAREDLIB_ABSTRACT_HPP

    #include <string>
    #include <iostream>

    #include "SharedLib/global.hpp"

    namespace Test
    {

    class SHAREDLIB_EXPORT SharedLibAbstract
    {

    public:
        SharedLibAbstract() = default;
        ~SharedLibAbstract() = default;
    
        void test() {
          std::cout << init();
        }
    
        std::string init() {
          return std::string("Not from this :(");
        }
    

    };

    } // namespace Test

    #endif // SHAREDLIB_ABSTRACT_HPP[/code]

    That's print "HELLOOOOWWW Not from this :("
    It's logic but that's not what i want!

    I tried:
    [code] void test() {
    std::cout << this->init();
    }

        virtual std::string init() {
          return std::string("Not from this :(");
        }[/code]
    

    in Abstract.hpp

    but I get:
    [code] debug/main.o: In function ZN4Test17SharedLibAbstractC2Ev': D:/Dev/C++/Projects/TestLib/testlib/SharedLib/src/SharedLib/Abstract.hpp:18: undefined reference to _imp___ZTVN4Test17SharedLibAbstractE'
    debug/main.o: In function ZN4Test17SharedLibConcreteC1Ev': D:/Dev/C++/Projects/TestLib/testlib/SharedLib/src/SharedLib/Concrete.hpp:16: undefined reference to _imp___ZTVN4Test17SharedLibConcreteE'
    collect2.exe: error: ld returned 1 exit status[/code]

    As error at compile time. (Pure virtual also).

    my final objective is to declare an interface in the abstract class (an "init" method) which must be implemented in the derived class and called from the base class.

    There is no best way than use: [code]static_cast<CRTP*>(this)->plow()[/code]
    ?
    Can't use Virtual (pure, final, ...) method in a shared dll's lib?

    Regards

    Pascal Blétard

    1 Reply Last reply
    0
    • dheerendraD Offline
      dheerendraD Offline
      dheerendra
      Qt Champions 2022
      wrote on last edited by
      #2

      Are you trying to build Qt Plugin ? You can look at the examples "How to create Qt Plugins". You will be able to achieve your objective very easily.

      Dheerendra
      @Community Service
      Certified Qt Specialist
      http://www.pthinks.com

      1 Reply Last reply
      0
      • C Offline
        C Offline
        calak
        wrote on last edited by
        #3

        No, not a plugin. It's shared codee between apps of a package.

        The problem is not the use of the lib (DLL, SO, whatever. ..) but the use of virtual methods in this lib.

        1 Reply Last reply
        0
        • dheerendraD Offline
          dheerendraD Offline
          dheerendra
          Qt Champions 2022
          wrote on last edited by
          #4

          I have done it using the simple Qt plugins with pure virtual methods in the base class. It works beautifully. I have not tried your example.

          Dheerendra
          @Community Service
          Certified Qt Specialist
          http://www.pthinks.com

          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #5

            Hi,

            Are you really sure you are exporting everything correctly ?

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply
            0
            • C Offline
              C Offline
              calak
              wrote on last edited by
              #6

              yeah, i think

              Here's a list of all my files of this test project:

              testlib.pro
              [code]TEMPLATE = subdirs

              CONFIG +=

              SUBDIRS += SharedLib
              SomeApp \

              SomeApp.depends = SharedLib

              OTHER_FILES += .qmake.conf[/code]

              .qmake.conf
              [code]ROOT_DIR = $$PWD/../..
              PROJECT_DIR = $$PWD
              LIB_DIR = $$ROOT_DIR/Common

              BIN_OUT_DIR = $$PWD/../bin/
              LIB_OUT_DIR = $$BIN_OUT_DIR/lib/

              INCLUDEPATH +=[/code]

              SomeApp/SomeApp.pro
              [code]QMAKE_CXXFLAGS += -std=c++0x

              TEMPLATE += app

              QT += core
              QT -= gui

              CONFIG +=
              CONFIG += console
              CONFIG += qtwarn_on
              CONFIG -= app_bundle

              INCLUDEPATH +=
              $$PWD/src/
              $$PROJECT_DIR/SharedLib/src/

              LIBS += -L$$LIB_OUT_DIR -lSharedLib
              DESTDIR = $$BIN_OUT_DIR

              SOURCES += src/main.cpp[/code]

              SomeApp/src/main.cpp
              [code]
              #include <QCoreApplication>

              #include <string>
              #include <iostream>

              #include "SharedLib/Concrete.hpp"

              int main(int argc, char *argv[])
              {
              QCoreApplication a(argc, argv);

              std::cout << "HELLOOOOWWW\n";
              
              Test::SharedLibConcrete foo;
              foo.test();
              
              return a.exec&#40;&#41;;
              

              }[/code]

              SharedLib/SharedLib.pro
              [code]QMAKE_CXXFLAGS *= -std=c++11

              TEMPLATE = lib

              CONFIG += shared
              CONFIG +=

              DEFINES += SHAREDLIB_LIBRARY

              INCLUDEPATH += $$PROJECT_DIR/SharedLib/src/

              HEADERS +=
              src/SharedLib/global.hpp
              src/SharedLib/Abstract.hpp
              src/SharedLib/Concrete.hpp

              DESTDIR = $$LIB_OUT_DIR[/code]

              SharedLib/src/SharedLib/global.hpp
              [code]#ifndef DEMOFILE_GLOBAL_HPP
              #define DEMOFILE_GLOBAL_HPP

              #include <QtCore/QtGlobal>

              #if defined(SHAREDLIB_LIBRARY)

              define SHAREDLIB_EXPORT Q_DECL_EXPORT

              #else

              define SHAREDLIB_EXPORT Q_DECL_IMPORT

              #endif

              #endif // DEMOFILE_GLOBAL_HPP[/code]

              SharedLib/src/SharedLib/Concrete.hpp
              [code]#ifndef SHAREDLIB_CONCRETE_HPP
              #define SHAREDLIB_CONCRETE_HPP

              #include <string>

              #include "SharedLib/global.hpp"
              #include "SharedLib/Abstract.hpp"

              namespace Test
              {

              class SHAREDLIB_EXPORT SharedLibConcrete : public SharedLibAbstract
              {
              public:
              SharedLibConcrete() : SharedLibAbstract() {
              }
              ~SharedLibConcrete() = default;

                  std::string plow() {
                    return std::string("Yeah, that's ruleZ!");
                  }
              

              };

              } // namespace Test

              #endif // SHAREDLIB_CONCRETE_HPP[/code]

              And finally, the SharedLib/src/SharedLib/Abstract
              [code]#ifndef SHAREDLIB_ABSTRACT_HPP
              #define SHAREDLIB_ABSTRACT_HPP

              #include <string>
              #include <iostream>

              #include "SharedLib/global.hpp"

              namespace Test
              {
              class SHAREDLIB_EXPORT SharedLibAbstract
              {
              public:
              SharedLibAbstract() = default;
              ~SharedLibAbstract() = default;

                  void test() {
                    std::cout this->plow();
                  }
              
                  std::string plow() {
                    return std::string("Not from this :(");
                  }
              

              };

              } // namespace Test

              #endif // SHAREDLIB_HPP[/code]

              That compiles fine but prints "Not from this :(", logic, it call the same scope method...

              But, if i put the "plow" method as virtual, like that (or as pure virtual method):
              [code]#ifndef SHAREDLIB_ABSTRACT_HPP
              #define SHAREDLIB_ABSTRACT_HPP

              #include <string>
              #include <iostream>

              #include "SharedLib/global.hpp"

              namespace Test
              {
              class SHAREDLIB_EXPORT SharedLibAbstract
              {
              public:
              SharedLibAbstract() = default;
              ~SharedLibAbstract() = default;

                  void test() {
                    std::cout this->plow();
                  }
              
                  virtual std::string plow() {
                    return std::string("Not from this :(");
                  }
              

              };

              } // namespace Test

              #endif // SHAREDLIB_HPP[/code]

              I get these errors:
              [code] ...
              debug/main.o: In function ZN4Test17SharedLibAbstractC2Ev': D:/Dev/C++/Projects/TestLib/testlib/SharedLib/src/SharedLib/Abstract.hpp:18: undefined reference to _imp___ZTVN4Test17SharedLibAbstractE'
              debug/main.o: In function ZN4Test17SharedLibConcreteC1Ev': D:/Dev/C++/Projects/TestLib/testlib/SharedLib/src/SharedLib/Concrete.hpp:16: undefined reference to _imp___ZTVN4Test17SharedLibConcreteE'
              collect2.exe: error: ld returned 1 exit status
              ...[/code]

              The only way it work is to use CRTP and modify Abstract.hpp and Concrete.hpp to:

              SharedLib/src/SharedLib/Concrete.hpp
              [code]#ifndef SHAREDLIB_CONCRETE_HPP
              #define SHAREDLIB_CONCRETE_HPP

              #include <string>

              #include "SharedLib/global.hpp"
              #include "SharedLib/Abstract.hpp"

              namespace Test
              {

              class SHAREDLIB_EXPORT SharedLibConcrete : public SharedLibAbstract<SharedLibConcrete>
              {

              public:
                  SharedLibConcrete() : SharedLibAbstract() {
                  }
                  ~SharedLibConcrete() = default;
              
                  std::string plow() {
                    return std::string("Yeah, that's ruleZ!");
                  }
              

              };

              } // namespace Test

              #endif // SHAREDLIB_CONCRETE_HPP[/code]

              And finally, the SharedLib/src/SharedLib/Abstract
              [code]#ifndef SHAREDLIB_ABSTRACT_HPP
              #define SHAREDLIB_ABSTRACT_HPP

              #include <string>
              #include <iostream>

              #include "SharedLib/global.hpp"

              namespace Test
              {
              template <class CRTP>
              class SHAREDLIB_EXPORT SharedLibAbstract
              {

              public:
                  SharedLibAbstract() = default;
                ~SharedLibAbstract() = default;
              
                  void test() {
                    std::cout << static_cast<CRTP*>(this)->plow();
                  }
              
                  std::string plow() {
                    return std::string("Not from this :(");
                  }
              

              };

              } // namespace Test

              #endif // SHAREDLIB_HPP[/code]

              Why i cant use virtual method?

              1 Reply Last reply
              0
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #7

                Why are your classes now become template classes ?

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                1 Reply Last reply
                0
                • C Offline
                  C Offline
                  calak
                  wrote on last edited by
                  #8

                  To apply crtp idiom. 'Cause i can't call derived "init" method from base class using virtual method (see error msg when i try to use virtual)

                  1 Reply Last reply
                  0
                  • M Offline
                    M Offline
                    mmoll
                    wrote on last edited by
                    #9

                    Without running a C++ name demangler I have to say that this looks like your compiler doesn't know where to instantiate the virtual table. Make one of your virtual functions non-inline and put it into a .cpp file, that should help.

                    Also, see here: http://www.parashift.com/c++-faq/link-errs-missing-vtable.html

                    1 Reply Last reply
                    0
                    • C Offline
                      C Offline
                      calak
                      wrote on last edited by
                      #10

                      Damn yes !

                      I'll test it monday. Thank you.

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved