[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.c++

Linkage Problem Question

Immortal Nephi

10/4/2008 2:57:00 AM

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
4 Answers

Paavo Helde

10/4/2008 12:11:00 PM

0

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<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!

hth
Paavo

Immortal Nephi

10/5/2008 10:40:00 PM

0

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 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<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.

Nephi

Paavo Helde

10/6/2008 6:03:00 AM

0

Immortal_Nephi@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);
}



microcassanova

10/6/2008 2:09:00 PM

0

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 "