microcassanova
10/6/2008 2:09:00 PM
On Oct 6, 11:02 am, Paavo Helde <nob...@ebi.ee> wrote:
> Immortal_Ne...@hotmail.com kirjutas:
>
>
>
>
>
> > On Oct 4, 7:10 am, Paavo Helde <nob...@ebi.ee> wrote:
> >> 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<typename 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(CallbackBase& callback);
>
> lib.cpp:
>
> void Run(CallbackBase& 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 "