1

I am doing C++ coding on Linux about boost::bind.

The return data type of boost::bind is a function object, which is an input argument to another function bridge_set_pound_var_func.

But, bridge_set_pound_var_func's input argument must be a function pointer. bridge_set_pound_var_func's interface cannot be changed.

The code is as follows:

#include <boost/bind.hpp>
#include <iostream>
using namespace boost;

class myA
{
 public:

     int bridge_set_pound_var_func( int (*pound_var_func)(const char *, char *, void *), void *arg ) { std::cout << "bridge_set_pound_func is called " << std::endl ; return 0; }
 };

 class myC
 {
  public:
        myA *myOA;
        int func(const char * poundVar , char * t1, void * t2);

        int myCCall() { myOA->bridge_set_pound_func( (boost::bind(&myC::func, this)), (void *)this ); return 0;}

 };

 int myC::func(const char * poundVar , char * t1, void * t2)
 {
     std::cout << "myC::func is called " << std::endl;
     return 1;

  }

 int main()
 {
      myC myCO ;
      myC *m1p = &myCO ;
      m1p->myCCall() ;

      return 0 ;
 }

 // EOF

I got compile error:

 error: no matching function for call to 

 'myA::bridge_set_pound_func(boost::_bi::bind_t<int (&)(const char*, char*, void*), boost::_mfi::dm<int ()(const char*, char*, void*), myC>, boost::_bi::list1<boost::_bi::value<myC*> > >, void*)'


  note: candidates are: int myA::bridge_set_pound_func(int (*)(const char*, char*, void*), void*)

Any help will be appreciated.

And, the interface of bridge_set_pound_var_func cannot be changed because it needs to be called by many other functions.

This is the new code that work. But, "myC::func is called" is not printed, why ?

#include <boost/bind.hpp>
#include <boost/function.hpp>

#include <iostream>
using namespace boost;

class myA
{
 public:

 int bridge_set_pound_var_func( const boost::function3<int, const char *, char *, void *> f, void *arg )  { std::cout << "bridge_set_pound_var_func is called " << std::endl ; return 0; }

};

 typedef  int (*funcPtr)(const char *, char *, void *) ;

 typedef boost::function0<int&> boostBindFuncType;

 class myC
 {
  public:
   myA *myOA;
   int func(const char * poundVar , char * t1, void * t2);

   int myCCall()
   {

     std::cout << "myCCall is called " << std::endl;
     myOA->bridge_set_pound_var_func( (boost::bind(&myC::func, this, _1, _2, _3)), (void *)this );

     return 0;

   }

 };

 int myC::func(const char * poundVar , char * t1, void * t2)
 {
  std::cout << "myC::func is called " << std::endl;
  return 1;

 }

 int main()
 {
    myC myCO ;
    myC *m1p = &myCO ;
    m1p->myCCall() ;

   return 0 ;
 }

I cannot change the interface of bridge_set_pound_var_func, which is called by many other functions. Is is possible to transform boost::bind returned function object to a function pointer?

7
  • Side note: why not use the C++11 functional library? Commented Sep 14, 2012 at 22:03
  • this is a small part of a very large project. how to use C++11 functional lib ? thanks Commented Sep 14, 2012 at 22:05
  • Using better names would make your example code more comprehensible. myA and myC don't tell me anything, and you don't use f1 anywhere in the sample code. f1 seems to be myA::bridge_set_pound_func() -- correct? And so the myA object is not actually yours, and that is the interface that is fixed? Commented Sep 14, 2012 at 22:29
  • Just make a helper function and pass a pointer to the helper function. You can code the helper function to do whatever you want, including invoking a boost::function. Commented Sep 14, 2012 at 22:36
  • 1
    possible duplicate of How can I cast or convert boost bind to C function pointer? Commented Sep 14, 2012 at 23:02

3 Answers 3

2

Traditionally the final void * argument passed to callbacks is user defined data. If this is the case for you you can create a helper function that will let you pass functors. the only trouble is that you need to ensure that the user data exists until the callback will no longer be called - and that will depend a lot on your program structure. I'm just going to leak the object as thats the easiest way to ensure it continues to exist. ( Though you'll also have problems with the existance of the containing myC object ).

class myC
{
  public:
    myA *myOA;

    //NOTE: I've removed the void* ptr here, which should be user data.
    // If you still need it you'll need to bind it away at functor creation time.
    int func(const char * poundVar , char * t1);

    int myCCall()
    {
      //TODO: Fix this intentional leak.
      boost::function<int(const char*, char*)> * fn = new boost::function<int(const char*,char*)>( boost::bind(&myC::func,this) );
      //Call our helper function instead of `set_pound_func`.
      set_pound_func_with_functor(myOA, fn );
      return;
    }
};

// Function that is really passed to `set_pound_func` when 
// set_pound_func_with_functor is called.
// It converts the user data back to a boost function and calls it.
int pound_func_with_functor(const char* d1, char* d2, void* user_data)
{
  boost::function<int(const char*,char*)> * fn = static_cast< boost::function<int(const char*, char*) >( user_data );
  return (*fn)(d1,d2);
}

//Helper function to make set_pound_func work with boost functions instead.
//NOTE: You are required to ensure the fn argument exists for long enough...
void set_pound_func_with_functor( myA * myOA, boost::function<int(const char *, char *)> & fn )
{
   myOA->bridge_set_pound_var_func( &pound_func_with_functor, &fn );
}
Sign up to request clarification or add additional context in comments.

Comments

2

There are no ways to convert boost::bind result to function pointer.

Use boost::function

int bridge_set_pound_var_func
( const boost::function<int(const char *, char *, void *)>& f, void *arg )

call as

myOA->bridge_set_pound_var_func( (boost::bind(&myC::func, this, _1, _2, _3)),
(void *)this );

or use template parameter

template<typename Func>
int bridge_set_pound_var_func( const Func& f, void *arg )

call as in first case.

You cannot convert result of boost::bind or boost::function to function-pointer.

I think read this will be interestring.

demote boost::function to a plain function pointer

In your case - you cannot use target, so, look at answer of Ian

19 Comments

Thanks, but errors: testBoostBind.cpp:11: error: expected unqualified-id before '<' token testBoostBind.cpp:11: error: expected ',' or '...' before '<' token testBoostBind.cpp: In member function 'int myC::myCCall()': testBoostBind.cpp:33: error: no matching function for call to 'myA::bridge_set_pound_var_func(boost::_bi::bind_t<int, boost::_mfi::mf3<int, myC, const char*, char*, void*>, boost::_bi::list4<boost::_bi::value<myC*>, boost::arg<1>, boost::arg<2>, boost::arg<3> > >, void*)' testBoostBind.cpp:11: note: candidates are: int myA::bridge_set_pound_var_func()
The syntax function<int(const char *, char *, void *)> is correct ?
@runnerfrank : With any non-ancient compiler, yes, that's correct. What version of what compiler are you using?
@runnerfrank : When you're using the old/portable syntax, you need to use boost::function2 rather than boost::function (see the docs). In any case, GCC 4.3.2 is more than recent enough to use the syntax shown in the answer, so you must have some other problem we're not seeing. What version of Boost are you using?
@runnerfrank : You are using an ancient version of Boost -- 1.33.1 is from Dec. 2005. Do yourself a favor and update to something released within the last 7 years. ;-]
|
0

The only thing you can pass as a function pointer is a function. No function objects, no lambdas, no nothing. Just global functions.

2 Comments

"no lambdas" Captureless lambdas are fine. "Just global functions." Static member functions are fine.
Strictly, both of those are directly equivalent.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.