Linkage Problem Question

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Immortal_Nephi@hotmail.com

    Linkage Problem Question

    You have written several global functions inside header code. Then,
    you create either static library or dynamic linked library. All
    global functions can be reuseable to the main() function when you
    include header code.

    One problem is that you have created one function. You want to place
    it in the main's source code. You may not want to move it back to the
    header code. The C++ Compiler will compile and link without any
    problems if one function is defined outside of header code.

    For example:

    // Func.h header
    void ReadWrite(); // function phototype

    void Func1() {}
    void Func2() {}
    void Func3() {}

    void Run()
    {
    Func1();
    Func2();
    Func3();
    ReadWrite();
    }

    // main.cpp source code
    #include "Func.h"

    void ReadWrite() // define ReadWrite() here
    {
    }

    int main()
    {
    Run();
    return 0;
    }

    You can see what I mean. Func1(), Func2(),Func3() , and Run() are
    always unmodified in the .lib or .dll. You want to modify ReadWrte()
    in main.cpp source code.

    If you forget to define ReadWrite(), then C++ Compiler succeeds to
    compile, but it fails to link. The pointer to function is only the
    option. You should bind ReadWrite() where Run() can executes
    ReadWrite().

    If you forget to define pointer to function, then C++ Compiler
    succeeds to compile and link before executing program can crash with
    null of pointer to function.

    Please suggest the best practice how .lib and .dll can call
    ReadWrite() in main.cpp source code.

    Nephi
  • Paavo Helde

    #2
    Re: Linkage Problem Question

    Immortal_Nephi@ hotmail.com kirjutas:
    You have written several global functions inside header code. Then,
    you create either static library or dynamic linked library. All
    global functions can be reuseable to the main() function when you
    include header code.
    >
    One problem is that you have created one function. You want to place
    it in the main's source code. You may not want to move it back to the
    header code. The C++ Compiler will compile and link without any
    problems if one function is defined outside of header code.
    >
    For example:
    >
    // Func.h header
    void ReadWrite(); // function phototype
    >
    void Func1() {}
    void Func2() {}
    void Func3() {}
    >
    void Run()
    This should be:

    inline void Run()
    {
    Func1();
    Func2();
    Func3();
    ReadWrite();
    }
    >
    // main.cpp source code
    #include "Func.h"
    >
    void ReadWrite() // define ReadWrite() here
    {
    }
    >
    int main()
    {
    Run();
    return 0;
    }
    >
    You can see what I mean. Func1(), Func2(),Func3() , and Run() are
    always unmodified in the .lib or .dll. You want to modify ReadWrte()
    in main.cpp source code.
    If I understand correctly, you want to call Run() from main.cpp and you
    want that Run() would call back another function in main.cpp.

    So this is essentially a callback mechanism. In C you would pass a
    callback function pointer to the Run() function. In C++ you can use
    templates instead, with the benefit that in addition to a plain function
    you can pass a functor object holding some state, when needed.

    template<typena me CALLBACK>
    void Run(CALLBACK callback) {
    Func1();
    Func2();
    Func3();
    callback();
    }

    ....

    int main()
    {
    Run(ReadWrite);
    return 0;
    }

    >
    If you forget to define ReadWrite(), then C++ Compiler succeeds to
    compile, but it fails to link.
    This is a good thing, isn't it?
    Please suggest the best practice how .lib and .dll can call
    ReadWrite() in main.cpp source code.
    Your example concerned calling ReadWrite() from a function in an exported
    header file. This is not inside .lib or .dll, which would be a totally
    different thing.

    If the function was indeed defined inside a lib or dll, the template
    approach would not work (without support to template export, which is not
    generally implemented). Instead I would go with defining an abstract base
    class in the library header, providing a derived class with needed
    overridden function in the main.cpp and passing a reference of the
    derived class object to the Run() function. In my experience passing a
    plain function pointer as a callback almost never suffices, the function
    almost always needs some context or state from the calling site to
    operate properly. And no, do not even mention global variables!

    hth
    Paavo

    Comment

    • Immortal_Nephi@hotmail.com

      #3
      Re: Linkage Problem Question

      On Oct 4, 7:10 am, Paavo Helde <nob...@ebi.eew rote:
      Immortal_Ne...@ hotmail.com kirjutas:
      >
      >
      >
      >
      >
      You have written several global functions inside header code.  Then,
      you create either static library or dynamic linked library.  All
      global functions can be reuseable to the main() function when you
      include header code.
      >
      One problem is that you have created one function.  You want to place
      it in the main's source code.  You may not want to move it back to the
      header code.  The C++ Compiler will compile and link without any
      problems if one function is defined outside of header code.
      >
      For example:
      >
      // Func.h header
      void ReadWrite(); // function phototype
      >
      void Func1() {}
      void Func2() {}
      void Func3() {}
      >
      void Run()
      >
      This should be:
      >
      inline void Run()
      >
      >
      >
      >
      >
      {
           Func1();
           Func2();
           Func3();
           ReadWrite();
      }
      >
      // main.cpp source code
      #include "Func.h"
      >
      void ReadWrite() // define ReadWrite() here
      {
      }
      >
      int main()
      {
           Run();
           return 0;
      }
      >
      You can see what I mean.  Func1(), Func2(),Func3() , and Run() are
      always unmodified in the .lib or .dll.  You want to modify ReadWrte()
      in main.cpp source code.
      >
      If I understand correctly, you want to call Run() from main.cpp and you
      want that Run() would call back another function in main.cpp.
      >
      So this is essentially a callback mechanism. In C you would pass a
      callback function pointer to the Run() function. In C++ you can use
      templates instead, with the benefit that in addition to a plain function
      you can pass a functor object holding some state, when needed.
      >
      template<typena me CALLBACK>
      void Run(CALLBACK callback) {
          Func1();
          Func2();
          Func3();
          callback();
      >
      }
      >
      ...
      >
      int main()
      {
           Run(ReadWrite);
           return 0;
      >
      }
      >
      If you forget to define ReadWrite(), then C++ Compiler succeeds to
      compile, but it fails to link.  
      >
      This is a good thing, isn't it?
      >
      Please suggest the best practice how .lib and .dll can call
      ReadWrite() in main.cpp source code.
      >
      Your example concerned calling ReadWrite() from a function in an exported
      header file. This is not inside .lib or .dll, which would be a totally
      different thing.
      >
      If the function was indeed defined inside a lib or dll, the template
      approach would not work (without support to template export, which is not
      generally implemented). Instead I would go with defining an abstract base
      class in the library header, providing a derived class with needed
      overridden function in the main.cpp and passing a reference of the
      derived class object to the Run() function. In my experience passing a
      plain function pointer as a callback almost never suffices, the function
      almost always needs some context or state from the calling site to
      operate properly. And no, do not even mention global variables!

      Hello, Paavo

      Thanks for explanation how template works. I understand that you
      can't bind ReadWrite() into Run(). Please give me example of class
      code. You should define Run() in base class. Put pure virtual
      ReadWrite() in the same base class. Then, base class is inside .lib
      or .dll.

      You write to include base class header code. You add second class to
      be derived from base class. Then, you can add ReadWrite() inside
      derived class. It overrides base class' ReadWrite(). You can use
      base class' Run() inside main(). Run() from base class will call
      ReadWrite() in derived class.

      Is my saying correct? If not, please correct me.

      Nephi

      Comment

      • Paavo Helde

        #4
        Re: Linkage Problem Question

        Immortal_Nephi@ hotmail.com kirjutas:
        On Oct 4, 7:10 am, Paavo Helde <nob...@ebi.eew rote:
        >Immortal_Ne... @hotmail.com kirjutas:
        >>
        >>
        >>
        >>
        >>
        You have written several global functions inside header code.
         Then, you create either static library or dynamic linked library.
         All global functions can be reuseable to the main() function when
        you include header code.
        >>
        One problem is that you have created one function.  You want to
        place it in the main's source code.  You may not want to move it
        back to th
        e
        header code.  The C++ Compiler will compile and link without any
        problems if one function is defined outside of header code.
        >>
        For example:
        >>
        // Func.h header
        void ReadWrite(); // function phototype
        >>
        void Func1() {}
        void Func2() {}
        void Func3() {}
        >>
        void Run()
        >>
        >This should be:
        >>
        >inline void Run()
        >>
        >>
        >>
        >>
        >>
        {
             Func1();
             Func2();
             Func3();
             ReadWrite();
        }
        >>
        // main.cpp source code
        #include "Func.h"
        >>
        void ReadWrite() // define ReadWrite() here
        {
        }
        >>
        int main()
        {
             Run();
             return 0;
        }
        >>
        You can see what I mean.  Func1(), Func2(),Func3() , and Run() are
        always unmodified in the .lib or .dll.  You want to modify
        ReadWrte() in main.cpp source code.
        >>
        >If I understand correctly, you want to call Run() from main.cpp and
        >you want that Run() would call back another function in main.cpp.
        >>
        >So this is essentially a callback mechanism. In C you would pass a
        >callback function pointer to the Run() function. In C++ you can use
        >templates instead, with the benefit that in addition to a plain
        >function you can pass a functor object holding some state, when
        >needed.
        >>
        >template<typen ame CALLBACK>
        >void Run(CALLBACK callback) {
        >    Func1();
        >    Func2();
        >    Func3();
        >    callback();
        >>
        >}
        >>
        >...
        >>
        >int main()
        >{
        >     Run(ReadWrite);
        >     return 0;
        >>
        >}
        >>
        If you forget to define ReadWrite(), then C++ Compiler succeeds to
        compile, but it fails to link.  
        >>
        >This is a good thing, isn't it?
        >>
        Please suggest the best practice how .lib and .dll can call
        ReadWrite() in main.cpp source code.
        >>
        >Your example concerned calling ReadWrite() from a function in an
        >exported header file. This is not inside .lib or .dll, which would be
        >a totally different thing.
        >>
        >If the function was indeed defined inside a lib or dll, the template
        >approach would not work (without support to template export, which is
        >not generally implemented). Instead I would go with defining an
        >abstract base class in the library header, providing a derived class
        >with needed overridden function in the main.cpp and passing a
        >reference of the derived class object to the Run() function. In my
        >experience passing a plain function pointer as a callback almost
        >never suffices, the function almost always needs some context or
        >state from the calling site to operate properly. And no, do not even
        >mention global variables!
        >
        >
        Hello, Paavo
        >
        Thanks for explanation how template works. I understand that you
        can't bind ReadWrite() into Run(). Please give me example of class
        code. You should define Run() in base class. Put pure virtual
        ReadWrite() in the same base class. Then, base class is inside .lib
        or .dll.
        >
        You write to include base class header code. You add second class to
        be derived from base class. Then, you can add ReadWrite() inside
        derived class. It overrides base class' ReadWrite(). You can use
        base class' Run() inside main(). Run() from base class will call
        ReadWrite() in derived class.
        >
        Is my saying correct? If not, please correct me.
        Yes, kind of, but there is actually no need to put Run() and ReadWrite()
        in the same class (for the callback scheme to work, that is). I sketch a
        solution where they are separate (not tested!):

        lib.h:

        class CallbackBase {
        public:
        virtual void operator()() = 0;
        virtual ~CallbackBase() {}
        };

        void Run(CallbackBas e& callback);


        lib.cpp:

        void Run(CallbackBas e& callback) {
        // ...
        callback();
        }

        main.cpp

        #include <iostream>

        class Callback_A: public CallbackBase {
        public:
        Callback_A(int state): state_(state) {}
        virtual void operator()() {
        std::cout << "Callback A, state=" << state_ << "\n";
        }
        private:
        int state_;
        };

        int main() {
        Callback_A my_callback(42) ;
        Run(my_callback );
        }



        Comment

        • microcassanova

          #5
          Re: Linkage Problem Question

          On Oct 6, 11:02 am, Paavo Helde <nob...@ebi.eew rote:
          Immortal_Ne...@ hotmail.com kirjutas:
          >
          >
          >
          >
          >
          On Oct 4, 7:10 am, Paavo Helde <nob...@ebi.eew rote:
          Immortal_Ne...@ hotmail.com kirjutas:
          >
          You have written several global functions inside header code.
           Then, you create either static library or dynamic linked library.
           All global functions can be reuseable to the main() function when
          you include header code.
          >
          One problem is that you have created one function.  You want to
          place it in the main's source code.  You may not want to move it
          back to th
          e
          header code.  The C++ Compiler will compile and link without any
          problems if one function is defined outside of header code.
          >
          For example:
          >
          // Func.h header
          void ReadWrite(); // function phototype
          >
          void Func1() {}
          void Func2() {}
          void Func3() {}
          >
          void Run()
          >
          This should be:
          >
          inline void Run()
          >
          {
               Func1();
               Func2();
               Func3();
               ReadWrite();
          }
          >
          // main.cpp source code
          #include "Func.h"
          >
          void ReadWrite() // define ReadWrite() here
          {
          }
          >
          int main()
          {
               Run();
               return 0;
          }
          >
          You can see what I mean.  Func1(), Func2(),Func3() , and Run() are
          always unmodified in the .lib or .dll.  You want to modify
          ReadWrte() in main.cpp source code.
          >
          If I understand correctly, you want to call Run() from main.cpp and
          you want that Run() would call back another function in main.cpp.
          >
          So this is essentially a callback mechanism. In C you would pass a
          callback function pointer to the Run() function. In C++ you can use
          templates instead, with the benefit that in addition to a plain
          function you can pass a functor object holding some state, when
          needed.
          >
          template<typena me CALLBACK>
          void Run(CALLBACK callback) {
              Func1();
              Func2();
              Func3();
              callback();
          >
          }
          >
          ...
          >
          int main()
          {
               Run(ReadWrite);
               return 0;
          >
          }
          >
          If you forget to define ReadWrite(), then C++ Compiler succeeds to
          compile, but it fails to link.  
          >
          This is a good thing, isn't it?
          >
          Please suggest the best practice how .lib and .dll can call
          ReadWrite() in main.cpp source code.
          >
          Your example concerned calling ReadWrite() from a function in an
          exported header file. This is not inside .lib or .dll, which would be
          a totally different thing.
          >
          If the function was indeed defined inside a lib or dll, the template
          approach would not work (without support to template export, which is
          not generally implemented). Instead I would go with defining an
          abstract base class in the library header, providing a derived class
          with needed overridden function in the main.cpp and passing a
          reference of the derived class object to the Run() function. In my
          experience passing a plain function pointer as a callback almost
          never suffices, the function almost always needs some context or
          state from the calling site to operate properly. And no, do not even
          mention global variables!
          >
          Hello, Paavo
          >
          Thanks for explanation how template works.  I understand that you
          can't bind ReadWrite() into Run().  Please give me example of class
          code.  You should define Run() in base class.  Put pure virtual
          ReadWrite() in the same base class.  Then, base class is inside .lib
          or .dll.
          >
          You write to include base class header code.  You add second class to
          be derived from base class.  Then, you can add ReadWrite() inside
          derived class.  It overrides base class' ReadWrite().  You can use
          base class' Run() inside main().  Run() from base class will call
          ReadWrite() in derived class.
          >
          Is my saying correct?  If not, please correct me.
          >
          Yes, kind of, but there is actually no need to put Run() and ReadWrite()
          in the same class (for the callback scheme to work, that is). I sketch a
          solution where they are separate (not tested!):
          >
          lib.h:
          >
          class CallbackBase {
          public:
                  virtual void operator()() = 0;
                  virtual ~CallbackBase() {}
          >
          };
          >
          void Run(CallbackBas e& callback);
          >
          lib.cpp:
          >
          void Run(CallbackBas e& callback) {
                  // ...
                  callback();
          >
          }
          >
          main.cpp
          >
          #include <iostream>
          >
          class Callback_A: public CallbackBase {
          public:
                  Callback_A(int state): state_(state) {}
                  virtual void operator()() {
                          std::cout << "Callback A, state=" << state_ << "\n";
                  }
          private:
                  int state_;
          >
          };
          >
          int main() {
                  Callback_A my_callback(42) ;
                  Run(my_callback );
          >
          >
          >
          }- Hide quoted text -
          >
          - Show quoted text -- Hide quoted text -
          >
          - Show quoted text -

          you can define in both lib and in main() ReadWrite(). U can force
          linker to use multiple definiton . there are options for multiple
          linkage. Then after linking linker uses in GCC "gnu.linker once
          section " even multiple definiton presents one function gets linked
          and code runs . other function will be moved to "discarded section of
          linker "

          Comment

          Working...