Page 1 of 2

Visual C++ compiling help

Posted: Wed Jun 09, 2010 8:24 am
by accelleon
tell me how this works:

i get this error when compiling:
Gay Visual C++ Compiler wrote:Error 8 error LNK2019: unresolved external symbol "struct PROGBAR_ * list" (?list@@3PAUPROGBAR_@@A) referenced in function "void __cdecl GUIInit(int)" (?GUIInit@@YAXH@Z) C:\Users\(no need to know my name :) )\Documents\Accel OS\Install\Floppy\Installer\Kernel\GUI.lib(GUI.obj)
Yet here's the top half of my test GUI driver from my os, where the error occurs:

Code: Select all

#include <VGA.h>

struct PROGBAR_//My progress bar struct for drawing
{
	bool used;
	int x;
	int y;
	int width;
	int height;
	byte color;
	byte fill;
};

typedef PROGBAR_ PROGBAR;//typedef for the struct

PROGBAR list[];//List of progress bars
int max_ctrls;//Global var for GUIDraw()
bool GUIInitialized = false;//Same as above

void GUIInit(int num_ctrls)
{
	max_ctrls = num_ctrls;//For the GUIDraw() function

	for(int i=0; i<max_ctrls; i+=1) // Set all entries to unused
		list[i].used = false;

	GUIInitialized = true;//Tell my GUIDraw() function that the GUI is initialized
}
(PS: the type "byte" is defined in "VGA.h" along with my VGA driver's functions)

I don't even have any code close to

Code: Select all

struct PROGBAR_ * list
in my GUIInit() function. I think this is another problem where Visual C++ complains about some other piece of code when the actual problem is in a totally different file.

If necessary I will post the rest of my GUI driver.

Re: Visual C++ compiling help

Posted: Wed Jun 09, 2010 11:39 am
by Andyhhp
I don't even have any code close to
Erm, yes you have!

Code: Select all

typedef PROGBAR_ PROGBAR;//typedef for the struct

PROGBAR list[];//List of progress bars

Code: Select all

list[i].used = false;
The error means that PROGBAR_ is not defined in any header files which you have included.

~Andrew

Re: Visual C++ compiling help

Posted: Wed Jun 09, 2010 5:55 pm
by accelleon
I defined PROGBAR_:

Code: Select all

struct PROGBAR_//My progress bar struct for drawing
{
   bool used;
   int x;
   int y;
   int width;
   int height;
   byte color;
   byte fill;
};
And I meant i never defined a pointer to PROGBAR_. And i don't define anything in GUIInit() except for the variable "i" used in the for loop.

So do i have to put the struct into a header and then include the header.

Edit: i placed the struct into "GUI.h" and included it into the code, but no luck same error.
heres the GUI.h file:

Code: Select all

#ifndef _GUI_
#define _GUI_

typedef unsigned char byte;

struct _PROGBAR_
{
	bool used;
	int x;
	int y;
	int width;
	int height;
	byte color;
	byte fill;
};

typedef _PROGBAR_ PROGBAR;

extern void GUIInit(int num_ctrls);
extern int CreateProgressBar(int x, int y, int width, int height, byte color);
extern void ProgressBarDestroy(int index);
extern void ProgressBarSetFill(int index, byte fill);
extern void ProgressBarSetColor(int index, byte color);
extern void GUIDraw(void);

#endif
Heres the full GUI.cpp:

Code: Select all

#include <VGA.h>
#include "GUI.h"

PROGBAR list[];
int max_ctrls;
bool GUIInitialized = false;

void GUIInit(int num_ctrls)
{
	max_ctrls = num_ctrls;
	for(int i=0; i<max_ctrls; i+=1)
		list[i].used = false;
	GUIInitialized = true;
}

int CreateProgressBar(int x, int y, int width, int height, byte color)
{
	int i=0;
	while(!list[i].used)
		i+=1;
	list[i].used = true;
	list[i].x = x;
	list[i].y = y;
	list[i].width = width;
	list[i].height = height;
	list[i].color = color;
	list[i].fill = 0;
	return i;
}

void ProgressBarDestroy(int index)
{
	list[index].used = false;
}

void ProgressBarSetFill(int index, byte fill)
{
	if(fill<100)
		list[index].fill = fill;
}

void ProgressBarSetColor(int index, byte color)
{
	list[index].color = color;
}

void GUIDraw(void)
{
	VGA::clearScreen(15);

	int x,y,x2,y2,color,fill;
	float tmp;

	for(int i=0; i<max_ctrls; i+=1)
	{
		if(!list[i].used)
			continue;
		x = list[i].x;
		y = list[i].y;
		x2 = x + list[i].width;
		y2 = y + list[i].height;
		color = list[i].color;
		VGA::drawRectangle(x,y,x2,y2,color);
		tmp = list[i].fill / 100;
		fill = list[i].width * tmp;
		VGA::drawRectangle(x,y,x+fill,y2,color,true);
	}
}

Re: Visual C++ compiling help

Posted: Wed Jun 09, 2010 6:36 pm
by halofreak1990
Correct me if I'm wrong, but under normal circumstances, an array is a pointer to a range of contiguous memory, so the notion of a pointer in the error message is correct.
As such, if you want to return an array from a function, you should write it as returning a pointer.

And you don't necessarily need that typedef. Just rewrite the

Code: Select all

};
at the end of your struct definition to

Code: Select all

} PROGBAR;
and remove the typedef, though I'm fairly certain that's not the cause for the problem.

If your struct would be referenced only inside that function and nowhere else, it should be fine if you declare it in the .c/.cpp file.
It only needs to be in the header if it's also used outside those functions.

Re: Visual C++ compiling help

Posted: Wed Jun 09, 2010 6:43 pm
by accelleon
but the thing is i don't return the PROGBAR struct in any function i only return its index in the array.

yea i know i could define the PROGBAR without the typedef after the struct like this:

Code: Select all

typedef struct PROGBAR_//My progress bar struct for drawing
{
   bool used;
   int x;
   int y;
   int width;
   int height;
   byte color;
   byte fill;
} PROGBAR;
I actually had that earlier till i changed it to see if it was causing the error.

And yea i don't use the struct outside of the functions in my GUI.cpp file. The only thing i want to know is why its throwing an "undefined external symbol" error at me when my struct isn't even used in anything other than my GUI code and it was defined in it.

Re: Visual C++ compiling help

Posted: Wed Jun 09, 2010 6:47 pm
by Mike
Hello,

PROGBAR list[] needs to be defined as either a pointer (PROGBAR* list) or an array of known size.

Re: Visual C++ compiling help

Posted: Wed Jun 09, 2010 7:24 pm
by accelleon
Thanks that worked. Well i know now that the Visual C++ will give an error that isn't very informative. Thanks again.

Re: Visual C++ compiling help

Posted: Wed Jun 09, 2010 11:11 pm
by halofreak1990
That's weird, I don't recall being forced to define a size for an array at compile time while declaring it like, for example

Code: Select all

char array[];
Though, if I'm correct, variable length arrays are a language extension that needs to be enabled if you want to use it.
Seems I have them enabled by default, since I've never had a compiler throw an error for using a variable-sized array.

I like variable-sized arrays for the simple reason that you can easily save memory by having your array only as large as needed.
But this means you need to be very careful if you don't want an overflow to occur.

Re: Visual C++ compiling help

Posted: Thu Jun 10, 2010 3:28 am
by Andyhhp
Sadly no,

There is no case in which a variable sized array can be implicitly declared. It simply doesnt work.

There are times when you could say "char buffer[] = "Hello World";" but that is an explicit declaration of how long the string is: The compiler can work it out at compile time.

Anything which is not explicitly evaluable at compiletime will result in an error because the compiler cannot work out how much space to reserve for it.

~Andrew

Re: Visual C++ compiling help

Posted: Mon Jun 28, 2010 12:33 pm
by Fanael
halofreak1990 wrote:Correct me if I'm wrong, but under normal circumstances, an array is a pointer to a range of contiguous memory, so the notion of a pointer in the error message is correct.
No, it's not. An array is an array, a pointer is a pointer, they're completely unrelated things, even though there is an implicit conversion from the former to the latter.

Re: Visual C++ compiling help

Posted: Mon Jun 28, 2010 1:58 pm
by Andyhhp
No, it's not. An array is an array, a pointer is a pointer, they're completely unrelated things, even though there is an implicit conversion from the former to the latter.
Nope - sadly you are wrong. Array syntax is just an abstraction to make pointers easier to deal with. In terms of C, an array name is a pointer to the beginning of the block of memory, and elemets of the array are accessed using (pointer + element_number*element_size).

~Andrew

Re: Visual C++ compiling help

Posted: Mon Jun 28, 2010 2:24 pm
by Fanael
Andyhhp wrote:Nope - sadly you are wrong. Array syntax is just an abstraction to make pointers easier to deal with. In terms of C, an array name is a pointer to the beginning of the block of memory, and elemets of the array are accessed using (pointer + element_number*element_size).
Heh, actually it's you who is wrong.
C standard wrote:Any number of derived types can be constructed from the object, function, and incomplete types, as follows:
— An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type. Array types are characterized by their element type and by the number of elements in the array.An array type is said to be derived from its element type, and if its element type is T, the array type is sometimes called ‘‘array of T’’.The construction of an array type from an element type is called ‘‘array type derivation.
[...]
—A pointer type may be derived from a function type, an object type, or an incomplete type, called the referenced type.A pointer type describes an object whose value provides a reference to an entity of the referenced type.A pointer type derived from the referenced type T is sometimes called ‘‘pointer to T’’. The construction of a pointer type from a referenced type is called ‘‘pointer type derivation.
So, they're distinct types, and there's only an implicit conversion:
C standard wrote:Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array,an expression that has type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.

Re: Visual C++ compiling help

Posted: Mon Jun 28, 2010 2:43 pm
by Andyhhp
You are getting caught up in the logical rules of the type checker.

Yes, in practice, those rules apply internally in the compiler. No, they do not appear outside the compiler.

For all intents and purposes, and to answer the original question, whenever the compiler spits the error in question (Error 8 error LNK2019: unresolved external symbol "struct PROGBAR_ * list"), the error could apply to either struct PROGBAR_ * list or struct PROGBAR_ list[].

As far as the programmer is concerned, arrays and pointers to the first element are synonomous when dealing with this error.

~Andrew

Re: Visual C++ compiling help

Posted: Mon Jun 28, 2010 3:48 pm
by Fanael
Andyhhp wrote:As far as the programmer is concerned, arrays and pointers to the first element are synonomous when dealing with this error.
Mainly because there was no array at all, since the code was erroneous (it's not possible to define an array of unknown size without initializer list), eh?

Really, please distinguish between pointers and arrays, they're totally different things, this difference can show up in real world, especially when using C++ templates.

Re: Visual C++ compiling help

Posted: Mon Jun 28, 2010 4:03 pm
by Andyhhp
That is not the point.

He was trying to make an array and yes, erroneously did not set either a length or initaliser list. The compiler then goes back and says "Oi - you have an undefined pointer here".

Why should I distinguish between two entities when the compiler doesnt?

The whole point of this thread is to explain what the error message meant. Despite the fact that it says "you have an undefined pointer", it means "you havnt set up this array correctly".

~Andrew