проблемка с _beginthreadex
От: maxis11 Украина  
Дата: 12.03.12 22:13
Оценка:
Проблема заключается в том, что функцию, которую нужно передать в поток, находится в классе, и к сожалению её нельзя обозначить как static
Ниже приведен исходный код:


class MTcp_server
{
    private:
    bool sock_inited;
    bool listening;
    char buff [1024];
    int clients;
    int serv_error;
    unsigned id_lstn;
    SOCKET serv_socket;
    sockaddr_in serv_addr;
    unsigned int __stdcall lstn (void*);
    public:
    int port;
    MTcp_server(int);
    int out_error ();
    void create_sock();
    void close_sock();
    void blind_serv();
    unsigned listen_start(int,void*);
    void listen_end (unsigned);
    void send (int);
    void send (double);
    void send (char);
    void send (char*);
    void send (string);
    void send (bool);
    unsigned int __stdcall foo (void*);
    ~MTcp_server();
};

// тут типо конструкторы и прочие функии, которые не какое отношение не имеют

unsigned MTcp_server::listen_start(int n, void* indata)
{
    if (listening==0)
    {
    if (listen(serv_socket,n))
    {
        serv_error=WSAGetLastError();
    }
    else
    {
        serv_error=0;
        listening=1;
        unsigned int id;
        _beginthreadex(NULL,0,lstn,indata,0, &id);
        return id;
    }
    }
}

unsigned int __stdcall MTcp_server::lstn (void* indata)
{
    MTcp_client_data client;
    int client_addr_size=sizeof(client.client_addr);
    while (client.client_socket=accept(serv_socket, (sockaddr *) &client.client_addr, &client_addr_size))
    {
        clients++;
        client.hst=gethostbyaddr ((char*)&client.client_addr.sin_addr.s_addr,4,AF_INET);
        unsigned clid;
        //_beginthreadex(NULL,0,foo,indata,0, &clid); //тут такая же проблема
    }
}

// дальше функции и деструктор класса

И вот тут проблема вышла:
H:\codeblocks\4\tststr\..\..\1\Test\Inet.hpp|142|error: argument of type 'unsigned int (MTcp_server:)(void*)' does not match 'unsigned int (*)(void*)'|
Пожайлуста помогите, буду очень благодарен (да если это важную роль сыграет, то компилятор: mingw (gcc 4.6.2))
c++ _beginthreadex потоки mingw
Re: проблемка с _beginthreadex
От: ParfenMyshkin  
Дата: 12.03.12 22:34
Оценка: 2 (1)
class A
{
.......
void some_method();

static void run(void *pArgs)
.......
};


void A::run(void *pArgs)
{
A *this_obj = static_cast<A*>(pArgs);
this_obj->some_method();
}

P.S. поздно, поэтому Ваш листинг не читал.
Re: проблемка с _beginthreadex
От: okman Беларусь https://searchinform.ru/
Дата: 13.03.12 05:30
Оценка: 3 (1)
Здравствуйте, maxis11, Вы писали:

M>Проблема заключается в том, что функцию, которую нужно передать в поток, находится в классе, и к сожалению её нельзя обозначить как static

M>Ниже приведен исходный код:
M>...

Передавайте в _beginthreadex адрес функции, находящейся в глобальном или анонимном
пространстве имен. А этой функции можно передать указатель на экземпляр класса,
из которого она сможет брать параметры и вызывать методы:
namespace {

unsigned int
_stdcall
ThreadProc(
    __in    VOID      * pParam
    )
{
    MTcp_server *pServer = (MTcp_server *)pParam;
    pServer->lstn();
    return 0;
}

} // namespace



unsigned MTcp_server::listen_start(int n, void* indata)
{
    if (listening==0)
    {
        if (listen(serv_socket,n))
        {
            serv_error=WSAGetLastError();
        }

        else
        {
            serv_error=0;
            listening=1;
            unsigned int id;

            // Если потоков несколько, можно придумать
            // другую схему для передачи indata.
            m_indata = indata;
            _beginthreadex(NULL, 0, ThreadProc, this, 0, &id);

            return id;
        }
    }
}
Re[2]: проблемка с _beginthreadex
От: maxis11 Украина  
Дата: 13.03.12 09:17
Оценка:
Здравствуйте, okman, Вы писали:

O>Здравствуйте, maxis11, Вы писали:


M>>Проблема заключается в том, что функцию, которую нужно передать в поток, находится в классе, и к сожалению её нельзя обозначить как static

M>>Ниже приведен исходный код:
M>>...

O>Передавайте в _beginthreadex адрес функции, находящейся в глобальном или анонимном

O>пространстве имен. А этой функции можно передать указатель на экземпляр класса,
O>из которого она сможет брать параметры и вызывать методы:
O>
O>namespace {

O>unsigned int
O>_stdcall
O>ThreadProc(
O>    __in    VOID      * pParam
O>    )
O>{
O>    MTcp_server *pServer = (MTcp_server *)pParam;
O>    pServer->lstn();
O>    return 0;
O>}

O>} // namespace



O>unsigned MTcp_server::listen_start(int n, void* indata)
O>{
O>    if (listening==0)
O>    {
O>        if (listen(serv_socket,n))
O>        {
O>            serv_error=WSAGetLastError();
O>        }

O>        else
O>        {
O>            serv_error=0;
O>            listening=1;
O>            unsigned int id;

O>            // Если потоков несколько, можно придумать
O>            // другую схему для передачи indata.
O>            m_indata = indata;
O>            _beginthreadex(NULL, 0, ThreadProc, this, 0, &id);

O>            return id;
O>        }
O>    }
O>}
O>


Спасибо огромное за помощь
Re: проблемка с _beginthreadex
От: Кодт Россия  
Дата: 13.03.12 09:53
Оценка: 3 (1)
Здравствуйте, maxis11, Вы писали:

M>Проблема заключается в том, что функцию, которую нужно передать в поток, находится в классе, и к сожалению её нельзя обозначить как static


Как насчёт посмотреть в сторону boost::thread ? Там удобная интеграция с bind и function.
Чтобы не руками писать переходник, как уже посоветовали выше.
Перекуём баги на фичи!
Re[2]: проблемка с _beginthreadex
От: maxis11 Украина  
Дата: 13.03.12 10:03
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, maxis11, Вы писали:


M>>Проблема заключается в том, что функцию, которую нужно передать в поток, находится в классе, и к сожалению её нельзя обозначить как static


К>Как насчёт посмотреть в сторону boost::thread ? Там удобная интеграция с bind и function.

К>Чтобы не руками писать переходник, как уже посоветовали выше.

Спасибо, посмотрю, хотя если честно я как то сторонними библиотеками не очень то люблю пользоваться, но если порекомендовали, почему бы и нет...
Re[3]: проблемка с _beginthreadex
От: Warturtle  
Дата: 13.03.12 11:51
Оценка: 2 (1)
Здравствуйте, maxis11, Вы писали:

M>Здравствуйте, Кодт, Вы писали:


К>>Здравствуйте, maxis11, Вы писали:


M>>>Проблема заключается в том, что функцию, которую нужно передать в поток, находится в классе, и к сожалению её нельзя обозначить как static


К>>Как насчёт посмотреть в сторону boost::thread ? Там удобная интеграция с bind и function.

К>>Чтобы не руками писать переходник, как уже посоветовали выше.

M>Спасибо, посмотрю, хотя если честно я как то сторонними библиотеками не очень то люблю пользоваться, но если порекомендовали, почему бы и нет...

Кстати, boost::bind и boost::function полезны не только из-за интеграции с boost::thread — они хорошо годятся еще например для написания собственных функций перебора, принимающих "делегат" для каждого элемента. Если в сишном стиле это может выглядеть так:
typedef bool (* ItemCallback)(ItemT item, void * data);
void EnumItems(ItemCallback cb, void * data)
{
    ...
    for (...) {
        if (!cb(item, data))
            break;
    }
    ...
}
...
bool ItemAction(ItemT item, void * pdata)
{
    ...
    DataT * data = *static_cast< DataT * >(pdata);
    ...
}
...
DataT data(p1, p2);
EnumItems(&ItemAction, &data);

то bind и function позволяют избавиться от "нетипобезопасной" упаковки-распаковки параметров:
typedef boost::function< bool (ItemT item) > ItemCallback;
void EnumItems(ItemCallback cb)
{
    ...
    for (...) {
        if (!cb(item))
            break;
    }
    ...
}
...
bool ItemAction(ItemT item, Param1T p1, Param2T & p2)
{
    ...
}
...
ItemCallback const & cb = boost::bind(&ItemAction, _1, p1, boost::ref(p2));
EnumItems(cb);

Да и вообще, бывает, что с ними можно писать меньше шаблонного кода (понятно, что нужные делегаты будут генерироваться по шаблону внутри function и bind, но в клиентской программе они точно будут меньше мозолить глаза=)).
Re[4]: проблемка с _beginthreadex
От: maxis11 Украина  
Дата: 13.03.12 16:42
Оценка:
Здравствуйте, Warturtle, Вы писали:

W>Здравствуйте, maxis11, Вы писали:


M>>Здравствуйте, Кодт, Вы писали:


К>>>Здравствуйте, maxis11, Вы писали:


M>>>>Проблема заключается в том, что функцию, которую нужно передать в поток, находится в классе, и к сожалению её нельзя обозначить как static


К>>>Как насчёт посмотреть в сторону boost::thread ? Там удобная интеграция с bind и function.

К>>>Чтобы не руками писать переходник, как уже посоветовали выше.

M>>Спасибо, посмотрю, хотя если честно я как то сторонними библиотеками не очень то люблю пользоваться, но если порекомендовали, почему бы и нет...

W>Кстати, boost::bind и boost::function полезны не только из-за интеграции с boost::thread — они хорошо годятся еще например для написания собственных функций перебора, принимающих "делегат" для каждого элемента. Если в сишном стиле это может выглядеть так:
W>
W>typedef bool (* ItemCallback)(ItemT item, void * data);
W>void EnumItems(ItemCallback cb, void * data)
W>{
W>    ...
W>    for (...) {
W>        if (!cb(item, data))
W>            break;
W>    }
W>    ...
W>}
W>...
W>bool ItemAction(ItemT item, void * pdata)
W>{
W>    ...
W>    DataT * data = *static_cast< DataT * >(pdata);
W>    ...
W>}
W>...
W>DataT data(p1, p2);
W>EnumItems(&ItemAction, &data);
W>

W>то bind и function позволяют избавиться от "нетипобезопасной" упаковки-распаковки параметров:
W>
W>typedef boost::function< bool (ItemT item) > ItemCallback;
W>void EnumItems(ItemCallback cb)
W>{
W>    ...
W>    for (...) {
W>        if (!cb(item))
W>            break;
W>    }
W>    ...
W>}
W>...
W>bool ItemAction(ItemT item, Param1T p1, Param2T & p2)
W>{
W>    ...
W>}
W>...
W>ItemCallback const & cb = boost::bind(&ItemAction, _1, p1, boost::ref(p2));
W>EnumItems(cb);
W>

W>Да и вообще, бывает, что с ними можно писать меньше шаблонного кода (понятно, что нужные делегаты будут генерироваться по шаблону внутри function и bind, но в клиентской программе они точно будут меньше мозолить глаза=)).

Всё хорошо, но я никак не могу собрать boost Libraries (1.49) как придумаю, как собрать либы, буду идти от простого к сложному, постепенно добавлять\заменять на более оптимальный вариант, ну всё, всем спасибо большое тему можно закрывать
Re[2]: проблемка с _beginthreadex
От: ParfenMyshkin  
Дата: 13.03.12 21:24
Оценка:
M>Проблема заключается в том, что функцию, которую нужно передать в поток, находится в классе, и к сожалению её нельзя обозначить как static


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