Модераторы: feodorv, GremlinProg, xvr, Fixin

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Нестатический метод класса в потоке, Передать CreateThread метод класса 
V
    Опции темы
null56
Дата 1.3.2010, 18:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: нет
Всего: 12



Всем привет
Задача: пытаюсь создать метод класса, который бы работал в потоке
Метод класса
Код

private:
            DWORD WINAPI create_thread(LPVOID lpParam);

Вызов №1:
Код

CreateThread(NULL, 0, create_thread, lpParameter, 0, &m_ThreadId);

Цитата

error C3867: 'Thread::create_thread': function call missing argument list; use '&Thread::create_thread' to create a pointer to member

Ок... вызов №2
Код

m_Thread = CreateThread(NULL, 0, &Thread::create_thread, lpParameter, 0, &m_ThreadId);

Цитата

error C2664: 'CreateThread' : cannot convert parameter 3 from 'DWORD (__stdcall Thread::* )(LPVOID)' to 'LPTHREAD_START_ROUTINE'

Приведение типа (хоть оно и нерекомендовано в мсдн) не помогло... вызов №3
Код

m_Thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&Thread::create_thread, lpParameter, 0, &m_ThreadId);

Цитата

'type cast' : cannot convert from 'DWORD (__stdcall Thread::* )(LPVOID)' to 'LPTHREAD_START_ROUTINE'


Итог: если объявить функцию статичной, компилятор пропускает
Вопрос: Неужели низя передать нестатический метод класса в поток???

Заранее благодарен за помощь

ЗЫ: вызовы произвожу также из метода этого же класса

Добавлено через 11 минут и 43 секунды
я могу лишь предположить, что несоответствие происходит из - за неявного параметра this перед именем функции
если моё предположение верно, то реально ли передать метод в поток?
PM MAIL   Вверх
null56
Дата 1.3.2010, 18:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: нет
Всего: 12



в соседней теме, смотрю, человек передал через объект через this в статику... похоже, что нельзя

Это сообщение отредактировал(а) null56 - 1.3.2010, 18:41
PM MAIL   Вверх
azesmcar
Дата 1.3.2010, 18:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 5
Всего: 211



Была уже такая тема (и не одна). 

http://forum.vingrad.ru/forum/topic-254872...read/index.html
PM   Вверх
GoldFinch
Дата 1.3.2010, 18:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 2
Всего: 26



Код

class Foo
{
     int __stdcall thread_func(void);

};

Foo foo;

union AllCastingCast
{
    int (__stdcall Foo::*met)();
    int (__stdcall *fn)(void*);
    // тут можно написать static_assert(sizeof(AllCastingCast)==sizeof(void*), "с этим методом фокус не пройдет");
} ptr = { &Foo::thread_func }

CreateThread(0, 0, ptr.fn, &foo, 0, 0);

метод объявляется как stdcall, this - параметр потока

разумеется это работает только для тех случаев, когда указатель на метод класса является указателем на код метода класса, 
т.е. в классе нет виртуальных функций и множественного наследования

Добавлено @ 18:58
Цитата(GoldFinch @  1.3.2010,  18:54 Найти цитируемый пост)
разумеется это работает только для тех случаев, когда указатель на метод класса является указателем на код метода класса, 
т.е. в классе нет виртуальных функций и множественного наследования

и разумеется используя этот код надо понимать что ты делаешь, в каких случаях он будет работать, а в каких нет, и как сделать так чтобы он работал в нужном тебе случае.

Добавлено @ 18:59
алсо рекомендую таки использовать boost.thread + boost.bind

Это сообщение отредактировал(а) GoldFinch - 1.3.2010, 19:03
PM MAIL ICQ   Вверх
null56
Дата 1.3.2010, 19:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: нет
Всего: 12



извиняюсь за дубляж, плохо искал значит

спасибо за помощь
PM MAIL   Вверх
GremlinProg
Дата 1.3.2010, 19:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



нет, null56, явно колбеком методы класса передавать нельзя,
т.к. они сильно зависят от конкретных реализаций и класса (как заметил GoldFinch), и компилятора,
лучше смотри в сторону azesmcar и X-3R1, это гораздо читабельнее, корректнее и проще

Это сообщение отредактировал(а) GremlinProg - 1.3.2010, 19:44


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
null56
Дата 1.3.2010, 20:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 721
Регистрация: 19.3.2008

Репутация: нет
Всего: 12



GremlinProg
я сделал через статику и через this, а параметры передал через сам объект... очень удобно и корректно показалось....
хотя вариант с шаблоном тоже не плохо смотрится....

Вариант GoldFinch интересный, но действительно опасный, выдирать адрес колбека... 
PM MAIL   Вверх
GoldFinch
Дата 1.3.2010, 20:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 2
Всего: 26



если туда в самом деле добавить статик_ассерт (например BOOST_STATIC_ASSERT  или static_assert в C+0x),
то все будет безопасно, код будет компилиться для тех методов с которыми все будет работать,
а для тех методов с которыми этот код работать не будет компилятор выдаст ошибку.
PM MAIL ICQ   Вверх
GremlinProg
Дата 1.3.2010, 20:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(GoldFinch @  1.3.2010,  22:51 Найти цитируемый пост)
если туда в самом деле добавить статик_ассерт (например BOOST_STATIC_ASSERT  или static_assert в C+0x),то все будет безопасно

о_О, чего сказал?


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
azesmcar
Дата 1.3.2010, 21:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 5
Всего: 211



Цитата(GoldFinch @  1.3.2010,  20:51 Найти цитируемый пост)
если туда в самом деле добавить статик_ассерт (например BOOST_STATIC_ASSERT  или static_assert в C+0x),
то все будет безопасно, код будет компилиться для тех методов с которыми все будет работать,
а для тех методов с которыми этот код работать не будет компилятор выдаст ошибку. 

 smile 
PM   Вверх
GoldFinch
Дата 1.3.2010, 21:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 2
Всего: 26



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

однако это можно проверить, сравнив размеры указателя на метод и обычного указателя (void*)
тот указатель на член класса, который не является обычным указателем, содержит дополнительную информацию, по этому его размер больше, чем размер обычного указателя

по этому можно написать 
Код

    union AllCastingCast
    {
       int (Foo::*met)();
       int (*fn)(void*);
    } ptr = { &Foo::thread_func }
    static_assert(sizeof(ptr)==sizeof(void*), "с этим методом код работать не будет, т.к. указатель на него не является обычным указателем");


Добавлено @ 21:15
те кто не использует компилятор с поддержкой C++0x могут использовать
Код

#include <boost/static_assert.hpp>
BOOST_STATIC_ASSERT(sizeof(ptr)==sizeof(void*));


Добавлено @ 21:20
впрочем счя проверил этот код на g++ 4.1.2  (codepad.org), он не работает (т.е. срабатывает ассерт).
что же, это означает, что тем кто пишет код под Windows на gcc - неповезло.

не стоит забывать, что это раздел про Windows, и тема про использование функции WinAPI CreateThread.
думаю что подавляющее большинство программистов используют msvc для создания windows-приложений.

Это сообщение отредактировал(а) GoldFinch - 1.3.2010, 21:27
PM MAIL ICQ   Вверх
GremlinProg
Дата 1.3.2010, 21:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106



Цитата(GoldFinch @  1.3.2010,  23:11 Найти цитируемый пост)
тот указатель на член класса, который не является обычным указателем, содержит дополнительную информацию, по этому его размер больше

ну, если бы мы разбирали конкретную реализацию компилятора, например как у Delphi, то да, могло бы прокатить,
только у Delphi нет таких богатых инструментов compile-time, чтобы такое там можно было использовать, так что - нет, это не вариант для си/си++

Добавлено через 3 минуты и 50 секунд
си просто не хранит this рядом с указателем на метод принципиально


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
GoldFinch
Дата 1.3.2010, 21:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 2
Всего: 26



GremlinProg, говоря о винде, мы скорее всего говорим о MSVC.

хотя конечно есть Borland C++ и есть Intel C++ compiler, и есть Clang (o_O) и много чего еще.
разумеется этот код может не работать ни на чем кроме MSVC.
однако это не повод не использовать этот код тем кто всегда юзает MSVC

в любом случае - имхо лучшее решение это boost.thread

Добавлено @ 21:28
Цитата(GremlinProg @  1.3.2010,  21:20 Найти цитируемый пост)
си просто не хранит this рядом с указателем на метод принципиально 

не понял.

this передается в метод отдельно, как 1й аргумент функции потока, потому что там указано что метод использует stdcall

Это сообщение отредактировал(а) GoldFinch - 1.3.2010, 21:29
PM MAIL ICQ   Вверх
GremlinProg
Дата 1.3.2010, 21:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2706
Регистрация: 9.8.2005
Где: Тюмень

Репутация: 99
Всего: 106




ничего не имею против g++, delphi и borland в целом,
я просто говорю, что для си, как такового, это решение не подходит,
т.к. си принципиально не хранит ни каких дополнительных данных рядом с указателями,
даже теми, которые выступают в роли членов класса


--------------------
"Гений всегда разумнее, чем умнее. Ум — это машина, разум — водитель этой машины."
PM WWW ICQ   Вверх
GoldFinch
Дата 1.3.2010, 21:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата



****


Профиль
Группа: Завсегдатай
Сообщений: 2141
Регистрация: 30.11.2008

Репутация: 2
Всего: 26



GremlinProg, помоему тема катится непонятно куда, пора бы заканчивать.
есть стандарт С++, в нем написано что указатель на член класса - это не обычный указатель и его представление в памяти зависит от реализации.

Цитата("ISO/IEC 14882-2003")

примечание к 4.11. p2:
__________________
52) (...) Note that a pointer to member is not a pointer to object or a pointer to function and the rules for conversions of
such pointers do not apply to pointers to members. In particular, a pointer to member cannot be converted to a void*.

8.3.3 p3:
The type “pointer to member” is distinct from the type “pointer”,
that is, a pointer to member is declared only by the pointer to member declarator syntax, and never by the
pointer declarator syntax.


также известно, как именно реализованы указатели на функции-члены классов в MSVC:
за исключением особых случаев, это обычные указатели, которые можно преобразовывать в другие указатели

Это сообщение отредактировал(а) GoldFinch - 1.3.2010, 21:55
PM MAIL ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0597 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.