开发者

How can I pass a C++ member function to a C API as a parameter

In my C++ program, I need to call this c API:

GConn* gnet_conn_new (const gchar *hostname,
                      gint port,
       开发者_如何学Go               GConnFunc func);

where GConnFunc is defined as:

void (*GConnFunc) (GConn *conn);

My question is if I have a C++ class and have a member function like:

Class A {
 public:
   A();
   void my_func (GConn* conn);
}

In my A::A() Constructor, how can I pass this->myfunc to gnet_conn_new as the GConnFunc parameter?

Thank you.


Most APIs provide a pointer-sized 'user data' argument, which would look like this:

GConn* gnet_conn_new (const gchar *hostname, 
                  gint port, 
                  GConnFunc func,
                  void* user_data); 

This would allow you to pass an instance in user_data and have your C function forward to the member function like this:

void my_func(GConn *conn, void* user_data)
{
    ((MyClass*)user_data)->MyMemberFunc(conn);
}

Perhaps your API has an alternative or similar 'user data' parameter somewhere. Otherwise, you can't really do it without globals or statics.


You are either going to need a wrapper function to handle this, or you can make my_func static (assuming it doesn't need to access any instance variables).


Short answer, you can't.

Long answer:

Given enough leeway by the API you need to call you can rig up a function that you simply register with and call as an intermediary. Usually callback functions allow you to include extra data that is passed to that function along with the information generated by the object making the callback. It is usually called something like "client_data" and is of type void* or long. When this is the case you can simply use this data to include enough information to call the function you want on the instance you want, such as tossing in a boost::function<>.

Note that this intermediary function that delegates to your member function can be a static member or a free function.

Unfortunately you don't have that option here so your work is going to be doubly tough. You really need some way to make sure that the correct instance is given the message and there's no way for you to identify that instance from the callback's data. There's a couple options that may or may not work for you:

  1. make sure you never use more than one instance as your callback target. Register this instance with a singleton or global of some sort that tracks one instance of a time to which to refer events of this type.

  2. Register as many instances as you want and just make sure they all get the message and then either deal with it or don't. You might use a sort of 'chain of responsibility' here where the target is given the opportunity to deal with an event and then returns something letting the loop know if it should continue or stop.

In conclusion, there's no direct way to do what you want but there may be answers to getting what you need if you consider the options. Any function used as a callback supplied to a C API function must be referable as a function pointer, not a member pointer of any kind...and unfortunately not a functor either. C does not know how to deal with thees things, so your callback must be a free function or a static member.


A non-static member function in a C++ class has a hidden "this" parameter. If you could hypothetically convert it to C, the function would translate as:

void A_my_func (A * const this, GConn* conn);

There's not really a way to do this conversion in your code automatically, although you could write a wrapper function using the prototype above and pass a pointer to it to a C function.

The usual way to handle this is to pass either a free (non-member) function, or a class static function. Neither of these types has the hidden parameter.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜