1
votes

I am struggling to use boost::function and boost::bind correctly to bind the passed object and member function into a boost::function which than is later called when data are in the queue

I am working on a multi producer single consumer queue for inter-thread communication. The basic idea is to provide a template class. When data published into the queue, the subscriber gets the data via a callback function which has to supply on subscription.

Note: ... denotes places where I omit code for legibility reasons

T is the type which is stored in the queue

template <typename T>
class pipeline_mpsc
{...};

The subscribe function

  template <typename FUNC, class OBJ>
  bool subscribe(FUNC fn, OBJ obj)
  {
    bool loc_return = false;
    if (Callback_fn_ == NULL)
    {

      boost::function<void(const T &)> BoundCallback(boost::bind(fn, obj, _1));

      Callback_fn_ = &BoundCallback;
      boost::thread th(&pipeline_mpsc::Callbackcaller, this, &BoundCallback); //pipeline.hpp[38, 25]
      loc_return = true;
    }
    return loc_return;
  };
void Callbackcaller(boost::function<void(const T &)> *Callback_fn)  {
   ...
   Callback_fn(loc_tmp); //pipeline.hpp[96, 18]
};

How I call the subscribe function

laserscan_sub_->subscribe(&LidarFovFilter::laserscan_callback, this); //LidarFovFilter.cpp[25, 73]

Prototype of the Callback function

void LidarFovFilter::laserscan_callback(const LaserScan &scan)

When I compile it I get following error from gcc:

‘Callback_fn’ cannot be used as a function

pipeline.hpp[96, 18]:In instantiation of ‘void pipeline_mpsc::Callbackcaller(boost::function) [with T = LaserScan]’:

pipeline.hpp[38, 25]:required from ‘bool pipeline_mpsc::subscribe(FUNC, OBJ) [with FUNC = void (LidarFovFilter::

)(const LaserScan&); OBJ = LidarFovFilter*; T = LaserScan]’

LidarFovFilter.cpp[25, 73]: required from here

From what I read how to use boost::bind and boost::function I think it my code should work (but obviously it doesn't).I am at loss here why it doesn't. Where is my mistake? Help would be really appricated.

1
Just out of curiosity: Are you working with a pre c++11 compiler? Unless you are restricted like this, there are way better solutions with the latest standard and lambda functions. - πάντα ῥεῖ
It wouldn't have worked anyway, even if there wasn't any build errors. Reason being that &BoundCallback is a pointer to a local object, one that would go out of scope and its life-time end before the thread. - Some programmer dude
@πάνταῥεῖ: Thank you for the tip I will look into it :) - Markus
@Someprogrammerdude: (*Callback_fn)(loc_tmp); is in a while loop (and more) which I omitted as it wasn't part of the problem but thank you for your objection:) - Markus
Not really an "objection" but a serious problem. You save a pointer to a local variable whose life-time ends before you use Callback_fn_. Example: if (some_condition) { int local_variable = 5; my_pointer = &local_variable; } /* PROBLEM AHEAD! local_variable no longer exists and my_pointer is invalid */ - Some programmer dude

1 Answers

0
votes

Issue is you pass a pointer to a boost::function - you need to dereference first:

void Callbackcaller(boost::function<void(const T &)> *Callback_fn)  {
   ...
   (*Callback_fn)(loc_tmp); //pipeline.hpp[96, 18]
};