Re[8]: Преобразование указателей
От: dupamid Россия  
Дата: 15.11.03 17:47
Оценка:
А теперь всплыло, странное что-то твориться...
Re[3]: Преобразование указателей
От: Кодт Россия  
Дата: 16.11.03 15:51
Оценка:
Здравствуйте, Нартов Андрей Евгеньевич, Вы писали:

A>>уточните зачем это надо.

НАЕ>например, сделать нить (CreateThread()) из нестатической member function

<>

НАЕ>Но ведь должен быть какой-то способ сделать такое преобразование указателей?


Преобразование указателей — нет такого способа (в общем виде). И вот почему.

Указатель на функцию или статический метод — это указатель в сегменте кода. Его размер для intel/win32 равен 4.
Указатель на метод — это совершенно иное явление. Он содержит разнообразную дополнительную информацию — о виртуальном методе, о виртуальной базе — и достигает размера 20 байт.

Чтобы передать в нить связку (closure) объекта и метода, нужно воспользоваться шлюзом (thunk).
Пример
template<class V>
V* assert_non_null(V* v) { assert(v != NULL); return v; }

template<class T>
struct Thunk
{
  typedef T Type;
  typedef Thunk<T> This;
  typedef void (*Type::Method)();

  Type* obj_;
  Method mtd_;

  Thunk(Type* obj, Method mtd) : obj_(assert_non_null(obj)), mtd_(assert_non_null(mtd)) {}

  static DWORD CALLBACK thunk_proc(LPVOID param)
  {
    This* thunk = assert_non_null(reinterpret_cast<This*>(param));
    thunk->play();
    delete thunk;
    return 0;
  }

  void play()
  {
    (obj_->*mtd_)();
  }
};

///

class Greeting
{
public:
  void hello();
  void goodbye();
};

///

Greeting a, b;

CreateThread(Thunk<Greeting>::thunk_proc, new Thunk<Greeting>(&a, &Greeting::hello));
CreateThread(Thunk<Greeting>::thunk_proc, new Thunk<Greeting>(&b, &Greeting::goodbye));

В более общем виде — можно делать шлюз для boost::function
DWORD CALLBACK boost_function_thunk(LPVOID param)
{
  boost::function0<void>* pfn = reinterpret_cast<boost::function0<void>*>(param);
  (*pfn)();
  delete pfn;
  return 0;
}

///

CreateThread(boost_function_thunk, new boost::function0<void>(&a, &Greeting::hello));
Перекуём баги на фичи!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.