Вопрос:

Привести указатель на функцию-член к обычному указателю

c++ pointers casting

11547 просмотра

6 ответа

6365 Репутация автора

В настоящее время у меня есть класс такого вида, сокращенный для простоты:

class MyClass {
    public: 
        MyClass();
        void* someFunc(void* param);
}

Теперь мне нужно вызвать функцию такого типа (не принадлежащую ни к какому классу и которую я, к сожалению, не могу изменить ), но которую я должен вызвать в любом случае:

void secondFunc(int a, int b, void *(*pCallback)(void*));

Теперь мне нужно передать адрес someFunc экземпляра.

Неработающий образец:

MyClass demoInstance;
// some other calls
secondFunc( 1, 2, demoInstance::someFunc() );

Я пробовал также с приведениями типа:

(void* (*)(void*)) demoInstance::someFunc;
reinterpret_cast<(void* (*)(void*))>(demoInstance::someFunc);

Как я могу вызвать эту функцию с функцией-членом класса в качестве параметра, чтобы она могла использовать ее в качестве обратного вызова?

Любая идея или замечание приветствуется. Спасибо и привет Тобиас

Автор: Atmocreations Источник Размещён: 18.11.2010 01:02

Ответы (6)


8 плюса

41719 Репутация автора

Вы не можете вызвать функцию-член напрямую. Указатели на функции-члены не относятся к указателям на функции.

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

Автор: Jonathan Grynspan Размещён: 18.11.2010 01:06

0 плюса

2901 Репутация автора

class MyClass 
{
public: 
    MyClass();
    void* someFunc(void* param);
};

void* callback(void*)
{
    MyClass instance;
    instance.someFunc(0 /* or whatever */);
}

void foo()
{
    secondFunc( 1, 2, callback);
}
Автор: cababunga Размещён: 18.11.2010 01:12

0 плюса

37 Репутация автора

Не видел части о невозможности изменить вторую функцию раньше.

Определите структуру с указателями на функцию-член и на объект:

struct MyData {
   MyStruct  *myInstance;
   (void *)(MyStruct::myFunction)(void *data);
   void * dataPointer ;
}

Создайте функцию, которая может вызывать правильный метод:

void *proxyFunc( MyData *data)
{
  return (data->myInstance->*(data->myFunction))(data->dataPointer);
}

Затем вызовите функцию 2 как:

MyData  dataP = { someInstance, &MyStruct::someFunc, &dataPtr };
secondFunc(proxyFunc, &dataP);
Автор: rldrenth Размещён: 18.11.2010 01:13

1 плюс

2046 Репутация автора

Существует множество способов сделать это. Поскольку имена C ++ искажены, вы не можете напрямую использовать их для нестатических функций. Однако, поскольку нестатические функции имеют те же сигнатуры, что и функции C, вы можете напрямую использовать их в качестве обратных вызовов. Так что для нестатических функций у вас могут быть обертки статических функций. Эта страница подробно объясняет этот подход.

Автор: Sridhar Iyer Размещён: 18.11.2010 01:31

5 плюса

12766 Репутация автора

Решение

Разница между функцией C и функцией-членом C ++ заключается в том, что функция C использует соглашение о вызовах cdecl , в то время как функции-члены используют это соглашение о вызовах (и вы даже не можете получить их адрес!).

Как я понимаю, вы действительно хотите, secondFunc()чтобы это вызывало функцию-член определенного экземпляра класса (давайте назовем это this). Ну, адреса функций-членов всех экземпляров определенного класса одинаковы. Чтобы передать указатель на объект, вам понадобится боковой канал. В этом случае это может быть статическая переменная. Или, если вы хотите поддержку MT, вам придется использовать Thread Local Storage (TLS),

Это требует одного обратного вызова для каждого SomeFuncчлена типа, но в любом случае вам понадобится диспетчер.

Автор: ruslik Размещён: 18.11.2010 01:56

0 плюса

11 Репутация автора

Смотрите этот образец:

#include <iostream>

class MyClass 
{
public: 
    MyClass()
    {
    }

    void* someFunc(void* param)
    {
        std::cout << "someFunc" << std::endl;
        return (void*)0;
    }
};

typedef void* (MyClass::*MemFun)(void*);

void secondFunc(int a, int b, MemFun fn)
{
    MyClass* ptr = 0;
    // This is dangerous! If the function someFunc do not operate the data in the class.
    // You can do this.
    (ptr->*fn)(0);
    std::cout << "Call me successfully!" << std::endl;
}

int main()
{
    secondFunc(1, 2, &MyClass::someFunc);

    system("pause");

    return 0;
}
Автор: lj_enjoylife Размещён: 18.11.2010 02:12
32x32