Pthread and recursive errors

Hi!

I'm building a program for a linux arm-powered robot... and I have some difficulty with my program.

The robot support phread librairy and the thread i'm building has the error "invalid use of void *(*)(void*)" ,

and in addition, there is a recurcive error of undefined reference to for pretty much all of the variables of my class.

I have planned to maybe change the class in a sigleton, if need be. I know, there'S no mutex nor destroyer for the moment but let's say it's fine for now...

libarmus is a librairy giving with the robot to cotrol it's input ouput, I made a small limited fake for windows, as my programming computer is windows so it's easier to test with that, than throught the robot it self.

Here's my codes:

encoder_class.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#ifndef ENCODER_OUT_H
#define ENCODER_OUT_H

#include "libarmus.h"
#include <assert.h>

#define MAX_MEMORY 100 //Maximum of values read from the encoders remembered...
#define MAX_NUM_ENCODER 6  //Maximum of Supported encoders
#define DELAY 100



class Encoder_Out
{
	enum call {First, Not_First};
	enum enc_Std {NONE, LEFT, RIGHT, BOTH};

    public:
        Encoder_Out();
        Encoder_Out(enum call first, enum enc_Std init_Std_Enc);
        ~Encoder_Out();

        bool Init();
        bool Init(int enc_num);
        int UseOnceOnFirstStartOnly();

        unsigned short int GetCounter()  const { return m_counter; }
        unsigned short int Get_RIGHT_ENCODER() 	 const { return m_encoder_val[ENCODER_RIGHT][m_counter]; }
        unsigned short int Get_RIGHT_ENCODER(int counter)  const { return m_encoder_val[ENCODER_RIGHT][counter]; }
        unsigned short int Get_LEFT_ENCODER()  const { return m_encoder_val[ENCODER_LEFT][m_counter]; }
        unsigned short int Get_LEFT_ENCODER(int counter)  const { return m_encoder_val[ENCODER_LEFT][counter]; }
        unsigned short int Get_ENCODER(int enc_num)  const { return m_encoder_val[enc_num][m_counter]; }
        unsigned short int Get_ENCODER(int enc_num, int counter) const { return m_encoder_val[enc_num][counter];  }


    private:
        static unsigned short int m_counter;
        static unsigned short int m_encoder_val[MAX_NUM_ENCODER][MAX_MEMORY];
     //  static unsigned short int m_encoder_thread;
        THREAD m_encoder_Thread;
        static bool m_act_encoder[MAX_NUM_ENCODER];

       


    private:
        void Encoder_Init(int);
        void Th_encoder();
        void Th_Counter();
};

#endif // ENCODER_OUT_H 


encoder_class.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include "encoder_class.h"


Encoder_Out::Encoder_Out()
{
    //ctor
}

Encoder_Out::Encoder_Out(enum call first, enum enc_Std init_Std_Enc)
{
    //ctor
	bool succes;
	if (!first == First)
	{
		Encoder_Out::UseOnceOnFirstStartOnly();
	}
	switch (init_Std_Enc)
	{
	case (0):
		succes = true;
		break;
	case (1):
		succes = Encoder_Out::Init(ENCODER_LEFT);
		break;
	case (2):
		succes = Encoder_Out::Init(ENCODER_RIGHT);
		break;
	case (3):
		succes = Encoder_Out::Init();
		break;
	}

	assert(succes);
}

Encoder_Out::~Encoder_Out()
{
    //dtor
}

int Encoder_Out::UseOnceOnFirstStartOnly()
{
	m_counter = 0;
    for (int i=0; i<MAX_NUM_ENCODER ; i++)
    {
    	m_act_encoder[i]=false;
    	for (int z=0; z<MAX_MEMORY; z++)
			{
    		m_encoder_val[i][z] = 0;
			}

    }

  pthread_create(&m_encoder_Thread, NULL, Th_encoder, (void*) 0);

	return 0;
}


bool Encoder_Out::Encoder_Out::Init()
{

    if (m_act_encoder[ENCODER_RIGHT]==0)
    	{
    	Encoder_Out::Encoder_Init(ENCODER_RIGHT);
    	};

    if (m_act_encoder[ENCODER_LEFT]==0)
    	{
    	Encoder_Out::Encoder_Init(ENCODER_LEFT);
    	};

    	return true;
}

bool Encoder_Out::Init(int enc_num)
{
    if (m_act_encoder[enc_num]==0)
    	{
		Encoder_Out::Encoder_Init(enc_num);
    	}
    	return true;
}

void Encoder_Out::Encoder_Init(int enc_num)
{
    ENCODER_Read(enc_num); //Discard first Value
    m_act_encoder[enc_num]=true;
}

void Encoder_Out::Th_encoder()
{
	int enc_num =0;
    while (1)
   {
    	for (int i=0; i<MAX_NUM_ENCODER ; i++)
    	{
    		if (m_act_encoder[i]==true)
			{
				enc_num=i;
				m_encoder_val[enc_num][m_counter]=ENCODER_Read(enc_num);
			}
    	}

    	m_counter++;
    	if (m_counter==MAX_MEMORY+1)
    	{
    		m_counter = 0;
    	}
			THREAD_MSleep(DELAY);
   }
}



main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <stdio.h>
#include "encoder_classes.h"

using namespace std;



int main()
{
 short int enc_out[2][100];


 Encoder_Out Encoder;
 Encoder.Init();

 for (int i=0; i<=100; i++)
 {

    //enc_out[ENCODER_LEFT][i]  = Encoder.Get_LEFT_ENCODER();
    //enc_out[ENCODER_RIGHT][i] = Encoder.Get_RIGHT_ENCODER();

    if (i==0)
    {
    printf("L=%d,R=%d", enc_out[ENCODER_LEFT][i], enc_out[ENCODER_RIGHT][i]);
    }
    else
    {
    	printf("L=%d,R=%d", enc_out[ENCODER_LEFT][i], enc_out[ENCODER_RIGHT][i]);
    }
 }

}


fake libarmus.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef LIBARMUS_H_INCLUDED
#define LIBARMUS_H_INCLUDED


#include <pthread.h>

#include <ctime>
#include <stdlib.h>

#include <windows.h>


#define THREAD pthread_t

const int ENCODER_RIGHT = 1;
const int ENCODER_LEFT = 0;

short int ENCODER_Read(int enc_num);
void THREAD_MSleep(int pause_time);



#endif // LIBARMUS_H_INCLUDED 


fake libarmus.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include "libarmus.h"

void gen_ran()
{
    unsigned int seed = time(0);
   srand(seed);
}


short int ENCODER_Read(int enc_num)
{
    return rand()%1000;
}

void THREAD_MSleep(int pause_time)
{
    Sleep(pause_time);
}


Thank you for you're help!
Last edited on
Did you link "encoder_class.cpp" to "main.cpp"? That would be my first thing to check when I see undefined reference errors. How about a copy\paste of the errors?
Thank you for you're reply... I'm using Code::Block, so it should do the linking it self, I will try running the compilling and liking manually...

here's the errors, with my thread quotted:

obj\Debug\encoder_class.o:C:\Users\Layfon\Documents\Project-Cpp\encoder_out\encoder_class.cpp|42|undefined reference to `Encoder_Out::m_counter'|
obj\Debug\encoder_class.o:C:\Users\Layfon\Documents\Project-Cpp\encoder_out\encoder_class.cpp|45|undefined reference to `Encoder_Out::m_act_encoder'|
obj\Debug\encoder_class.o:C:\Users\Layfon\Documents\Project-Cpp\encoder_out\encoder_class.cpp|48|undefined reference to `Encoder_Out::m_encoder_val'|
obj\Debug\encoder_class.o:C:\Users\Layfon\Documents\Project-Cpp\encoder_out\encoder_class.cpp|62|undefined reference to `Encoder_Out::m_act_encoder'|
obj\Debug\encoder_class.o:C:\Users\Layfon\Documents\Project-Cpp\encoder_out\encoder_class.cpp|67|undefined reference to `Encoder_Out::m_act_encoder'|
obj\Debug\encoder_class.o:C:\Users\Layfon\Documents\Project-Cpp\encoder_out\encoder_class.cpp|77|undefined reference to `Encoder_Out::m_act_encoder'|
obj\Debug\encoder_class.o:C:\Users\Layfon\Documents\Project-Cpp\encoder_out\encoder_class.cpp|87|undefined reference to `Encoder_Out::m_act_encoder'|
obj\Debug\encoder_class.o:C:\Users\Layfon\Documents\Project-Cpp\encoder_out\encoder_class.cpp|97|undefined reference to `Encoder_Out::m_act_encoder'|
obj\Debug\encoder_class.o:C:\Users\Layfon\Documents\Project-Cpp\encoder_out\encoder_class.cpp|100|undefined reference to `Encoder_Out::m_counter'|
obj\Debug\encoder_class.o:C:\Users\Layfon\Documents\Project-Cpp\encoder_out\encoder_class.cpp|100|undefined reference to `Encoder_Out::m_encoder_val'|
obj\Debug\encoder_class.o:C:\Users\Layfon\Documents\Project-Cpp\encoder_out\encoder_class.cpp|104|undefined reference to `Encoder_Out::m_counter'|
obj\Debug\encoder_class.o:C:\Users\Layfon\Documents\Project-Cpp\encoder_out\encoder_class.cpp|104|undefined reference to `Encoder_Out::m_counter'|
obj\Debug\encoder_class.o:C:\Users\Layfon\Documents\Project-Cpp\encoder_out\encoder_class.cpp|105|undefined reference to `Encoder_Out::m_counter'|
obj\Debug\encoder_class.o:C:\Users\Layfon\Documents\Project-Cpp\encoder_out\encoder_class.cpp|107|undefined reference to `Encoder_Out::m_counter'|
||=== Build finished: 14 errors, 0 warnings ===|


and with my thread not quoted...
C:\Users\Layfon\Documents\Project-Cpp\encoder_out\encoder_class.cpp||In member function 'int Encoder_Out::UseOnceOnFirstStartOnly()':|
C:\Users\Layfon\Documents\Project-Cpp\encoder_out\encoder_class.cpp|53|error: argument of type 'void (Encoder_Out::)()' does not match 'void* (*)(void*)'|
||=== Build finished: 1 errors, 0 warnings ===|


edit: managed to remove 3 errors!
Last edited on
If you're writing for Windows why aren't you using "CreateThread(...)"? http://msdn.microsoft.com/en-us/library/ms682453(VS.85).aspx
That second error says that you are passing a void type object as an argument where it is expecting a void type function pointer. I honestly think that using "CreateThread(...)" will simplify things for you.
****SOLVED*****


***Look at EDIT 2! ********


For one, I didn't that CreateThread(...) existed...

But the main reason is that I'm programing on windows environment and I'm trying to debug the code on windows is because the host platform as no display, or Human to Machine interface.

The final code will run from an ARM platform called ARMus, that run a small linux derived OS. That platform control an FPGA that does the work input and output.

Look up on youtube ARMus Sherbrooke to see the platform, the video "Grande Course" is pretty demonstrative.

So the way it really work is: The librairy libarmus.h is responsible for all the communication between Armus platform and the FPGA... Read_Encoder(int) ask the FPGA to return the number of "ticks" from the encoder since the last call. That mean that each time Read_Encoder is called, the value is reset to zero. The program I making kept in memory the last MAX_MEMORY return value of Read_Encoder so that more than one part of the program may intake the value of the encoder. And thus a thread is needed to read the encoder...

I made a libarmus cpp file just so that I can get error report from other program than the appropriate IDE, where debugging is... not very useful...

The ARMus platform as "native" support for pthread, but I doubt i could support any other threading library, as it need to be compiled for ARM (7 by memory), but not native ARM as the program is run from the Linux.

I actually found how to fix the pthread_create(...)... I just had to put the thread 'th_encoder' static and a pointer...

So:
.h
static void* Encoder_Out::Th_encoder(void *);
.cpp
1
2
3
4
Encoder_Out::Th_encoder(void *traSh)
{
/Code here
}


The errors are related are indeed linking error, but even linking manually failed:

Link.bat
1
2
3
4
5
6
7
set compiler_path="C:\Program Files (x86)\CodeBlocks\MinGW\bin"
set obj_path=C:\Users\Layfon\Documents\Project-Cpp\encoder_out\obj\Debug
set compiller=mingw32-g++.exe

cd /d %compiler_path%
%compiller% -o %obj_path%\ecod_debug %obj_path%\encoder_class.o %obj_path%\libarmus2.o %obj_path%\main.o
pause



But trying to compile without pthread on VS2010 instead of Code::Block output these errors: I believe they might be more significant:
1>------ Build started: Project: encod, Configuration: Debug Win32 ------
1>Build started 19/10/2011 6:44:18 PM.
1>InitializeBuildStatus:
1>  Touching "Debug\encod.unsuccessfulbuild".
1>ClCompile:
1>  encoder_class.cpp
1>  Generating Code...
1>  Compiling...
1>  main.cpp
1>  Generating Code...
1>encoder_class.obj : error LNK2001: unresolved external symbol "private: static unsigned short (* Encoder_Out::m_encoder_val)[100]" (?m_encoder_val@Encoder_Out@@0PAY0GE@GA)
1>encoder_class.obj : error LNK2001: unresolved external symbol "private: static bool * Encoder_Out::m_act_encoder" (?m_act_encoder@Encoder_Out@@0PA_NA)
1>encoder_class.obj : error LNK2001: unresolved external symbol "private: static unsigned short Encoder_Out::m_counter" (?m_counter@Encoder_Out@@0GA)
1>C:\Users\Layfon\Desktop\VIP\encod\Debug\encod.exe : fatal error LNK1120: 3 unresolved externals
1>
1>Build FAILED.
1>
1>Time Elapsed 00:00:02.31
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========


Thank you Computergeek01 for you're help and you're time!

EDIT: Found how to make pthread_create work!

EDIT 2:

For some reason, I managed to get it to work... I still don't understant why it didn't work with thread commented, however, it looks like a static fonction can't see a class variables... So I passed the pointer to the class to my static fonction, and linked the fonction var call to the class.
Now it "works" well it compiles... But if I try to Encoder.Get_RIGHT_ENCODER(), than printing the output... it fails...

Do not work:
1
2
3
4
5
6
7
8
9
10
 
 for (int i=0; i<100; i++) {
    printf("L=%d,R=%d\n", enc_out[ENCODER_LEFT][i], enc_out[ENCODER_RIGHT][i]);
    enc_out[ENCODER_LEFT][i]  = Encoder.Get_LEFT_ENCODER();
    enc_out[ENCODER_RIGHT][i] = Encoder.Get_RIGHT_ENCODER();
   printf("L=%d,R=%d\n", enc_out[ENCODER_LEFT][i], enc_out[ENCODER_RIGHT][i]);

    THREAD_MSleep(DELAY);

 }


Works:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 for (int i=0; i<100; i++)
 {
    printf("L=%d,R=%d\n", enc_out[ENCODER_LEFT][i], enc_out[ENCODER_RIGHT][i]);
    enc_out[ENCODER_LEFT][i]  = Encoder.Get_LEFT_ENCODER();
    enc_out[ENCODER_RIGHT][i] = Encoder.Get_RIGHT_ENCODER();
    count[i]= Encoder.GetCounter();

    THREAD_MSleep(DELAY);

 }

 for (int i=0; i<100; i++)
    {
      printf("L=%d,R=%d\n", enc_out[ENCODER_LEFT][i], enc_out[ENCODER_RIGHT][i]);
    }
 }


Also, enc_out[ENCODER_LEFT][i] always seem to keep the value 0, not the return of ENCODER_Read().

So, well, even though it compiles, it still doesn't work.

EDIT 3:

I identified the source of the problem:
(thptr->m_encoder_val[enc_num][(thptr->m_counter)])=ENCODER_Read(enc_num);

I can't seem to access de array...

If you could help me, I would be grateful!

*Also: removed cmd output now pretty useless, and it's was pretty much the same than last post...

EDIT 4: FOUND ALL OF MY ERRORS, YOUPPI!

Thanks for all the help!
Last edited on
Topic archived. No new replies allowed.