Как я могу передать функцию членства C++ API C в качестве параметра

В моей программе C++ я должен назвать этот c API:

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

где GConnFunc определяется как:

void (*GConnFunc) (GConn *conn);

Мой вопрос состоит в том, если я имею класс C++ и имею функцию членства как:

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

В моем A::A() Конструктор, как я могу передать this->myfunc кому: gnet_conn_new как GConnFunc параметр?

Спасибо.

11
задан James Kolpack 25 March 2010 в 16:44
поделиться

4 ответа

Большинство API предоставляют аргумент «пользовательские данные» размером с указатель, который будет выглядеть следующим образом:

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

Это позволит вам передать экземпляр в user_data и пусть ваша функция C переадресуется функции-члену следующим образом:

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

Возможно, ваш API имеет где-то альтернативный или аналогичный параметр «пользовательских данных». В противном случае вы не сможете этого сделать без глобалов или статики.

13
ответ дан 3 December 2019 в 05:33
поделиться

Коротко, нельзя.

Длинный ответ:

Имея достаточную свободу действий со стороны API, который вам нужно вызвать, вы можете настроить функцию, которую вы просто регистрируете и вызываете в качестве посредника. Обычно функции обратного вызова позволяют включать дополнительные данные, которые передаются этой функции вместе с информацией, сгенерированной объектом, выполняющим обратный вызов. Обычно он называется что-то вроде client_data и имеет тип void * или long. В этом случае вы можете просто использовать эти данные, чтобы включить достаточно информации для вызова нужной функции в нужном вам экземпляре, например, добавив boost :: function <>.

Обратите внимание, что эта промежуточная функция, которая делегирует вашу функцию-член, может быть статическим членом или свободной функцией.

К сожалению, у вас нет такой возможности, поэтому ваша работа будет вдвойне трудной. Вам действительно нужен способ убедиться, что правильный экземпляр получил сообщение, и у вас нет возможности идентифицировать этот экземпляр по данным обратного вызова. Есть пара вариантов, которые могут или не могут сработать для вас:

  1. убедитесь, что вы никогда не используете более одного экземпляра в качестве цели обратного вызова. Зарегистрируйте этот экземпляр с помощью синглтона или глобального некоторого вида, который отслеживает один экземпляр времени, на который следует ссылаться на события этого типа.

  2. Зарегистрируйте столько экземпляров, сколько хотите, и просто убедитесь, что все они получают сообщение, а затем либо разобрались с ним, либо нет. Вы можете использовать здесь своего рода «цепочку ответственности», где цели предоставляется возможность обработать событие, а затем она возвращает что-то, позволяющее циклу знать, следует ли ему продолжить или прекратить.

В заключение, нет прямого способа делать то, что вы хотите, но могут быть ответы на получение того, что вам нужно, если вы рассмотрите варианты. Любая функция, используемая в качестве обратного вызова для функции C API, должна рассматриваться как указатель на функцию, а не как указатель на член любого типа ... и, к сожалению, не как функтор. C не знает, что делать с этими вещами, поэтому ваш обратный вызов должен быть бесплатной функцией или статическим членом.

3
ответ дан 3 December 2019 в 05:33
поделиться

Нестатическая функция-член в классе C ++ имеет скрытый параметр this. Если бы вы могли гипотетически преобразовать его в C, функция была бы преобразована как:

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

На самом деле нет способа выполнить это преобразование в вашем коде автоматически, хотя вы могли бы написать функцию-оболочку, используя прототип выше, и передать указатель на нее в функция C.

Обычный способ справиться с этим - передать либо бесплатную (не являющуюся членом) функцию, либо статическую функцию класса. Ни один из этих типов не имеет скрытого параметра.

2
ответ дан 3 December 2019 в 05:33
поделиться

Вы либо вам понадобится функция-оболочка для обработки этого, или вы можете сделать my_func статическим (при условии, что ему не нужен доступ к каким-либо переменным экземпляра).

3
ответ дан 3 December 2019 в 05:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: