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?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
runner frank
  • 331
  • 1
  • 6
  • 13
  • Side note: why not use the C++11 `functional` library? – obataku Sep 14 '12 at 22:03
  • this is a small part of a very large project. how to use C++11 functional lib ? thanks – runner frank Sep 14 '12 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? – Mike C Sep 14 '12 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`. – David Schwartz Sep 14 '12 at 22:36
  • I can use a helper function with boost::bind returned data as input. But, how to transform the boost::bind data type to a function pointer so that bridge_set_pound_var_func can be called correctly ? thanks ! – runner frank Sep 14 '12 at 22:40
  • 1
    possible duplicate of [How can I cast or convert boost bind to C function pointer?](http://stackoverflow.com/questions/5962960/how-can-i-cast-or-convert-boost-bind-to-c-function-pointer) – ildjarn Sep 14 '12 at 23:02
  • All, it works, I post the new code in the original post. But, "myC::func is called " is not printed, why ? thanks ! – runner frank Sep 14 '12 at 23:37

3 Answers3

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

Community
  • 1
  • 1
ForEveR
  • 55,233
  • 2
  • 119
  • 133
  • 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, boost::_bi::list4, boost::arg<1>, boost::arg<2>, boost::arg<3> > >, void*)' testBoostBind.cpp:11: note: candidates are: int myA::bridge_set_pound_var_func() – runner frank Sep 14 '12 at 22:35
  • The syntax function is correct ? – runner frank Sep 14 '12 at 22:35
  • @runnerfrank : With any non-ancient compiler, yes, that's correct. What version of what compiler are you using? – ildjarn Sep 14 '12 at 22:40
  • http://liveworkspace.org/code/78300b4602cc0348ce5a1ba4ce1b5c19 yes, it's correct. Look at `boost::function` documentation. If your compiler cannot use this syntax - use old (i.e. `function`). – ForEveR Sep 14 '12 at 22:40
  • gcc version 4.3.2 20081105 (Red Hat 4.3.2-20) (GCC – runner frank Sep 14 '12 at 22:41
  • @ForEveR, I added #include , but the same error even though I used const boost::function& f – runner frank Sep 14 '12 at 22:44
  • Another thing is, the interface of bridge_set_pound_var_func cannot be changed. – runner frank Sep 14 '12 at 22:45
  • @runnerfrank not functional. `boost/function.hpp`. – ForEveR Sep 14 '12 at 22:49
  • @ForEveR, yes, I included , const boost::function& caused more errors: function_template.hpp: In static member function 'static R boost::detail::function::function_obj_invoker3::invoke(boost::detail::function::function_buffer&, T0, T1, T2) [with FunctionObj = boost::_bi::bind_t, boost::_bi::list1 > >, R = int, T0 = const char*, T1 = char*, T2 = void*]': – runner frank Sep 14 '12 at 22:54
  • @runnerfrank have no ideas. code should compiles well. you can use old syntax (i.e `boost::function`) – ForEveR Sep 14 '12 at 22:57
  • @ForEveR, yes, I used const boost::function& f, but error: rror: wrong number of template arguments (4, should be 1) – runner frank Sep 14 '12 at 23:07
  • @runnerfrank give a complete small example of your problem pls (if you use syntax as – ForEveR Sep 14 '12 at 23:10
  • 1
    @runnerfrank : When you're using the old/portable syntax, you need to use `boost::function2` rather than `boost::function` (see [the docs](http://www.boost.org/doc/libs/1_51_0/doc/html/function/tutorial.html#id1545352)). 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? – ildjarn Sep 14 '12 at 23:11
  • My boost version: BOOST_LIB_VERSION "1_33_1" – runner frank Sep 14 '12 at 23:20
  • @runnerfrank http://www.boost.org/doc/libs/1_33_1/doc/html/function/tutorial.html#id2688219 – ForEveR Sep 14 '12 at 23:23
  • if I used const boost::function2& f, error: wrong number of template arguments (1, should be 3) – runner frank Sep 14 '12 at 23:23
  • if I used const boost::function2& f, wrong number of template arguments (4, should be 3) – runner frank Sep 14 '12 at 23:23
  • All, it works, I post the new code in the original post. But, "myC::func is called " is not printed, why ? thanks ! – runner frank Sep 14 '12 at 23:46
  • 1
    @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. ;-] – ildjarn Sep 15 '12 at 00:16
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 );
}
Michael Anderson
  • 70,661
  • 7
  • 134
  • 187
0

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

Puppy
  • 144,682
  • 38
  • 256
  • 465