Raficcha 1 Denunciar post Postado Agosto 14, 2009 Gente, agora, estou criando um objeto para monitorar um arquivo com C+, e para fazer um loop sem ocupar o programa, estou utilizando (ou melho, tentando utilizar) threads. Fiz na minha classe uma função e estou criando um thread para dispará-la. Veja meu código abaixo: #include <cstdlib> #include <iostream> #include <windows.h> typedef const char* str; class FileCom{ private: str FileStr; FILE* arq; unsigned long iID; void WINAPI Execute(void); public: //construtor FileCom(); HANDLE hThread; //propriedades //metodos void Iniciar(str FileName); }; FileCom::FileCom(){ } void FileCom::Iniciar(str FileName){ FileCom::hThread = CreateThread(NULL,0,&(LPTHREAD_START_ROUTINE)Execute,NULL,0,&iID); } //metodos privados void FileCom::Execute(void){ } a linha do erro é a que tem "FileCom::hThread = CreateThread(NULL,0,&(LPTHREAD_START_ROUTINE)Execute,NULL,0,&iID);" no procedimento "Iniciar" do objeto o erro retornado é "argument of type 'void(FileCom::)()' dow not match 'DWORD(*)(void*)' Bom, gente, gostaria de saber se alguem pode me ajudar obrigado Compartilhar este post Link para o post Compartilhar em outros sites
VictorCacciari 42 Denunciar post Postado Agosto 14, 2009 Teu problema é novamente os ponteiros para funções. Ponteiros Membros de classes não são apenas ponteiros para funções. Se você declarar a sua função "Execute" como static e passar "this" como argumento, dará certo! Por exemplo: class Enigma { public: Enigma(int a) : secretNum(a) {}; static void PrintNum(void *myself); private: int secretNum; }; void Enigma::PrintNum(void *myself) { //Não esqueca de converter "myself" para poder acessar os outros membros da classe Enigma *eu = (Enigma*)myself; cout << "My secret number is: " << eu->secretNum << endl; } void ShowNum(Enigma *e, void (*f)(void*)) { (f)(e); } int main() { Enigma segredo(98765); Enigma segredo2(12345); ShowNum(&segredo, &Enigma::PrintNum); ShowNum(&segredo2, &Enigma::PrintNum); return 0; } Não fui muito feliz no exemplo, mas foi o melhor que consegui pensar... xD Em todas as funções membros de classes, é passado um "parametro oculto", que aponta para aquela classe... é precisamente "this". Nas funções que declaramos "static", "this" não é passado como parametro. Mas podemos passar ponteiros para funções static sem problemas. A solução é passar "this" como parametro para elas. Aconselho ler: http://www.codeproject.com/KB/cpp/FastDelegate.aspx Compartilhar este post Link para o post Compartilhar em outros sites
Raficcha 1 Denunciar post Postado Agosto 15, 2009 ow, intendi a função statica. Hum bom, vamos ver se endenti certo: nesta linha "Enigma *eu = (Enigma*)myself;", "Eu" é um ponteiro para um "enigma" e vai apontar para "myself" que é um "enigma" passado por parametro. isso ne? estou começando a entender melhor o C++.. hehe.. bom, mas e quanto à função "CreateThread", deixei ela desta maneira: FileCom::hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Execute,NULL,0,&iID); agora, sim, como declarei Execute como estatica, funcionou corretamente. Fiz ela baseada na sua "PrintNum", ou seja, ela recebe um parametro "myself". Porem, a função CreateThread, embora chame a função Execute, não passa nada em "myself". se eu tentar acessar "myself", o programa da erro e fecha... veja ai em baixo como esta o código fo programa: #include <cstdlib> #include <iostream> #include <windows.h> typedef const char* str; class FileCom{ private: str FileStr; FILE* arq; unsigned long iID; HANDLE hThread; int teste; static void WINAPI Execute(void *myself); public: //construtor FileCom(); //propriedades //metodos void Iniciar(str FileName); }; FileCom::FileCom(){ teste = 'a'; } void FileCom::Iniciar(str FileName){ void (*func)(void); FileCom::hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Execute,NULL,0,&iID); } //metodos privados void WINAPI FileCom::Execute(void *myself){ FileCom *pai = (FileCom*)myself; printf("%d", pai->teste); while (true) { printf("teste"); Sleep(1000); } } Vou procurar outras maneiras de se criar Threads, para ver se me ajuda. Mas gostaria de conseguir com a CreateThread(embora pertença a API do Windows, é simples utilizá-la) Compartilhar este post Link para o post Compartilhar em outros sites
VictorCacciari 42 Denunciar post Postado Agosto 15, 2009 sim, você entendeu o "macete" para usar membros static de classes. Mas no seu código, você tem que passar "this" como parametro para execute, por meio da função CreateThread. Não existem "outras maneiras" de se fazer isso, quem providencia as operações com threads é o sistema operacional! Cara, eu não sei como funcionam as threads no windows, mas em Linux ficaria: #include <iostream> #include <pthread.h> #include <unistd.h> #include <string> using std::string; class FileCom { private: unsigned limit; string name; pthread_t tHandle; //POSIX Threads retornam void* static void *Execute(void *myself); public: //construtor FileCom() {}; //propriedades //metodos void Iniciar(unsigned nm, string _name); void WaitThread(); }; //Vamos mandar ele mostrar "name", "limit" vezes, por uma thread. void *FileCom::Execute(void *myself) { FileCom *eu = (FileCom*)myself; int i=0; while (i < eu->limit) { std::cout << eu->name << "; "; sleep(1); i++; } return NULL; } //Aqui nós esperamos a execução da thread, para não terminarmos o programa e largar a thread rodando... void FileCom::WaitThread() { pthread_join(tHandle, NULL); } //A função que inicializa tudo! void FileCom::Iniciar(unsigned nm, string _name) { this->name = _name; this->limit = nm; //cria-se a thread, note a passagem the "this" como argumento! pthread_create(&tHandle, NULL, &FileCom::Execute, this); } int main() { FileCom f1, f2; f1.Iniciar(10, "teste_1"); f2.Iniciar(3, "abcd"); f1.WaitThread(); f2.WaitThread(); std::cout << std::endl; return 0; } e o output foi: victor@matrix:~/Desktop$ ./a.out teste_1; abcd; teste_1; abcd; teste_1; abcd; teste_1; teste_1; teste_1; teste_1; teste_1; teste_1; teste_1; victor@matrix:~/Desktop$ Compartilhar este post Link para o post Compartilhar em outros sites
Raficcha 1 Denunciar post Postado Agosto 16, 2009 Huhu... cara, aogra intendi, eu não tinha passado "this" no CreateThread hehe olha só, me animei tando que fiz ate um objeto parecido com um TTimer do Delphi... hehe #include <cstdlib> #include <iostream> #include <windows.h> typedef const char* str; class TTimer{ private: unsigned long iID; HANDLE hThread; static void WINAPI ChamaCallback(void *myself); public: int Interval; bool Active; TTimer(); void (*OnTimer)(int teste); void Iniciar(); }; TTimer::TTimer(){ TTimer::Interval = 1000; TTimer::OnTimer = NULL; TTimer::Active = false; } void TTimer::Iniciar(){ TTimer::hThread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ChamaCallback,this,0,&iID); } void WINAPI TTimer::ChamaCallback(void *myself){ //cria um ponteiro para a classe pai TTimer *pai = (TTimer*)myself; while (true) { if (pai->Active = true){ pai->OnTimer(1); } Sleep(pai->Interval); } } agora vou voltar para o FileCom, hehe, logo volto aqui para postar denovo...hehehe Compartilhar este post Link para o post Compartilhar em outros sites
VictorCacciari 42 Denunciar post Postado Agosto 16, 2009 =D Boa! Mas, cara, você não precisa escrever TTimer::hThread, ou TTimer::Active... na declaração da função ja está especificado que é para usar objetos da classe TTimer, se quiser, use this->hThread, this->Active... Compartilhar este post Link para o post Compartilhar em outros sites
Raficcha 1 Denunciar post Postado Agosto 17, 2009 A sim, logo ia pedir isso, então eu utlizo "::" so na declaração das funções e dentro dela então eu utilizo "this->propriedade".. ou então somente "propriedade" (neste caso, utlizo so "propriedade" caso não exista nenhuma variavel local com este nome).. isso né? Compartilhar este post Link para o post Compartilhar em outros sites
VictorCacciari 42 Denunciar post Postado Agosto 17, 2009 O operador ::, é um operador de escopo de simbolos. http://en.wikipedia.org/wiki/Scope_resolution_operator#C.2B.2B Por exemplo: a::b pode ser lido como: Objeto 'b' que pertence ao namespace 'a'. Você pode usar o operador '::' sempre que quiser acessar um simbolo que está em um namespace diferente! por exemplo: void MinhaClasse::Teste() { std::cout << "Olá Mundo!" << std::endl; } Compartilhar este post Link para o post Compartilhar em outros sites
Raficcha 1 Denunciar post Postado Agosto 17, 2009 Cara, estamos fazendo deste tópico uma aula de C++.. hehe.. espero que não tenha problemas se continuar ampliando ele... bom, então. Vou precisar de umas informações sobre GUI's agora. Não gostaria de desenhar telas com a API do Windows (na verdade nem nunca tentei) gostaria de saber sobre a GTK pois gostaria que meus programas ficassem disponíveis para Linux tambeim. Então. Suponhetemos que eu tenha feito uma interface gráfica utilizando a GTK. Eu preciso adicionar muitas dlls ao meu programa? fica muito grande? Você conhece outras maneira de desenhar interfaces sem a GTK e que você recomente dar uma olhada? Hehe, sei que tem bastante coisa pra aprende ainda antes de começar com as janelas, mas gostaria de começar a fazer uns programas mais bonitos (nada contra os de "tela preta", alias, eu gosto dos meus programas feitos com essa telinha, mas se eu fizer um programa e colocar na internet, gostaria que tivesse uma interface gráfica) Compartilhar este post Link para o post Compartilhar em outros sites
VictorCacciari 42 Denunciar post Postado Agosto 17, 2009 Cara, sobre ampliar o tópico não é problema, desde que não mudemos o assunto. Sobre GUI's ja tem MUITA coisa no fórum. Se você der uma pesquisada vai ver só! :P Mas, eu curto a Qt. Fica um pouco grande pois você tem que distribuir duas (ou mais, mas no geral são duas) dll's com o seu executável (+- 5mb). O problema com as threads e a classe ja foi resolvido, marcarei o tópico como resolvido. Se não encontrar a informação que precisa após uma busca no fórum, não hesite em criar outro! http://forum.imasters.com.br/public/style_emoticons/default/thumbsup.gif Compartilhar este post Link para o post Compartilhar em outros sites
Raficcha 1 Denunciar post Postado Agosto 17, 2009 Hehe. Ok cara, logo volto ai.. hehe.. muito obrigado por enquanto Compartilhar este post Link para o post Compartilhar em outros sites