I wrote a class, k_video split between a .hpp and a .cpp file. It compiles just fine, but when I try to link it into the kernel, I get tons of undefined references. I tried changing the linking order, but to no avail. Can anyone help?
I'm running Arch linux with a 4.4.3 GCC cross compiler setup.
video.hpp:
Code: Select all
#ifndef __VIDEO_HPP
#define __VIDEO_HPP
namespace kernel
{
class k_screen
{
public:
k_screen(void *, unsigned short, unsigned short);
k_screen();
void clear();
k_screen &operator<<(char const * str);
// Print a single character to screen.
k_screen &operator<<(char const c);
// Print a character value to screen
k_screen &operator<<(unsigned char const c);
// Print a signed integer to screen.
k_screen &operator<<(signed long integer);
// Print an unsigned integer to screen.
k_screen &operator<<(unsigned long integer);
// Print an address to screen. (Automatically 'hex' mode.)
k_screen &operator<<(void * ptr);
k_screen &operator<<(void (*formatter)());
static void putc(char const c);
static void setBase(unsigned char const bass);
private:
k_screen(k_screen&);
k_screen& operator=(k_screen const &);
// Print a null-terminated string to screen. CR/LF at end of string.
// @param ptr Pointer to the string to be printed.
void write(char const * ptr);
// Column Number
static unsigned char csr_x;
static unsigned char csr_y;
static unsigned char color;
static unsigned char base;
static unsigned short height;
static unsigned short width;
static unsigned short *mem_addr;
};
extern void endl();
extern void hex();
extern void dec();
}
#endif
Code: Select all
#include <video.hpp>
namespace kernel
{
k_screen::k_screen(void *addr, unsigned short ht, unsigned short wd)
{
mem_addr = reinterpret_cast<unsigned short *>(addr);
height = ht;
width = wd;
color = 0x0F;
csr_x = 0;
csr_y = 0;
}
void k_screen::clear()
{
for(int i = 0; i < width * height; i++)
{
mem_addr[i] = ' ' | (color << 8);
}
csr_x = 0;
csr_y = 0;
}
k_screen &k_screen::operator << (const char *str)
{
write(str);
return *this;
}
k_screen &k_screen::operator << (const char c)
{
putc(c);
return *this;
}
k_screen &k_screen::operator << (const unsigned char c)
{
unsigned char tmp_base = base;
base = 16;
operator<<(static_cast<unsigned long>(c));
base = tmp_base;
return *this;
}
k_screen &k_screen::operator << (long integer)
{
unsigned long new_int;
if (integer < 0)
{
putc('-');
new_int = integer * -1;
}
else
{
new_int = integer;
}
return operator<<(new_int);
}
k_screen &k_screen::operator<<(unsigned long integer)
{
// prepare C string buffer (array)
char buf[40]; // enough for 2^128 in decimal notation!
char* idx = buf; // pointer into the array
// "slice off" digits from the back with the modulo operator
do
{
unsigned char digit = integer % base;
if (digit < 10)
{
*idx++ = '0' + digit;
}
else
{
*idx++ = 'A' + (digit - 10);
}
} while ((integer /= base) > 0);
// for hex output, add leading zeroes to "round" length to power of 2,
// and "0x" to declare hexadecimal base.
if (base == 16)
{
while ((idx - buf) < 8) // 32 bit - 8 hex digits
{
*idx++ = '0';
}
*idx++ = 'x';
*idx++ = '0';
}
if (base == 2)
{
while ((idx - buf) < 32) // 32 bit - 32 binary digits
{
*idx++ = '0';
}
*idx++ = 'b';
}
// reverse everything between buf and idx
char * begidx = buf; // first unreversed character
char * endidx = idx - 1; // last unreversed character
while (begidx < endidx)
{
// exchange characters, move indexes
char tmp = *endidx;
*endidx-- = *begidx;
*begidx++ = tmp;
}
*idx++ = 0; // terminate string
write(buf); // write string
return *this;
}
k_screen &k_screen::operator<<(void * ptr)
{
// store adress as number in an integer
unsigned long address = reinterpret_cast<unsigned long>(ptr);
// adresses always in hexadecimal notation
unsigned char tmp_base = base;
base = 16;
operator<<(static_cast<unsigned long>(address));
base = tmp_base;
return *this;
}
k_screen &k_screen::operator<<(void (*formatter)())
{
// execute the formatter function
formatter();
return *this;
}
void k_screen::putc(const char c)
{
switch (c)
{
case '\n':
csr_x = width;
break;
case '\t':
csr_x += 7 - (csr_x % 8);
break;
default:
mem_addr[((csr_y * width + csr_x) * 2)] = (c | (color << 8));
break;
}
if (csr_x == width)
{
csr_x = 0;
csr_y++;
}
if (csr_y * width >= height * width)
{
unsigned short* dest_ptr = mem_addr;
unsigned short* src_ptr = mem_addr + width;
while (src_ptr < (mem_addr + height * width))
{
// copy characters one line up
*dest_ptr++ = *src_ptr++;
}
while (dest_ptr < (mem_addr + height * width))
{
// fill last line with spaces
*dest_ptr++ = ' ' | color << 8;
}
csr_y--;
}
}
void k_screen::setBase(const unsigned char bass)
{
base = bass;
}
void endl()
{
k_screen::putc('\n');
}
void hex()
{
k_screen::setBase(16);
}
void dec()
{
k_screen::setBase(10);
}
void k_screen::write(char const * ptr)
{
while (*ptr != '\0')
{
putc(*ptr++);
}
}
}
Code: Select all
[me@myhost Pri]$ make
src/video.o: In function `kernel::k_screen::k_screen(void*, unsigned short, unsigned short)':
/video.cpp:8: undefined reference to `kernel::k_screen::mem_addr'
/video.cpp:9: undefined reference to `kernel::k_screen::height'
/video.cpp:10: undefined reference to `kernel::k_screen::width'
/video.cpp:11: undefined reference to `kernel::k_screen::color'
/video.cpp:12: undefined reference to `kernel::k_screen::csr_x'
/video.cpp:13: undefined reference to `kernel::k_screen::csr_y'
src/video.o: In function `kernel::k_screen::k_screen(void*, unsigned short, unsigned short)':
/video.cpp:8: undefined reference to `kernel::k_screen::mem_addr'
/video.cpp:9: undefined reference to `kernel::k_screen::height'
/video.cpp:10: undefined reference to `kernel::k_screen::width'
/video.cpp:11: undefined reference to `kernel::k_screen::color'
/video.cpp:12: undefined reference to `kernel::k_screen::csr_x'
/video.cpp:13: undefined reference to `kernel::k_screen::csr_y'
src/video.o: In function `kernel::k_screen::clear()':
/video.cpp:20: undefined reference to `kernel::k_screen::mem_addr'
/video.cpp:20: undefined reference to `kernel::k_screen::color'
/video.cpp:18: undefined reference to `kernel::k_screen::width'
/video.cpp:18: undefined reference to `kernel::k_screen::height'
/video.cpp:22: undefined reference to `kernel::k_screen::csr_x'
/video.cpp:23: undefined reference to `kernel::k_screen::csr_y'
src/video.o: In function `kernel::k_screen::operator<<(unsigned char)':
/video.cpp:40: undefined reference to `kernel::k_screen::base'
/video.cpp:41: undefined reference to `kernel::k_screen::base'
/video.cpp:43: undefined reference to `kernel::k_screen::base'
src/video.o: In function `kernel::k_screen::operator<<(unsigned long)':
/video.cpp:70: undefined reference to `kernel::k_screen::base'
/video.cpp:68: undefined reference to `kernel::k_screen::base'
src/video.o:/src/video.cpp:82: more undefined references to `kernel::k_screen::base' follow
src/video.o: In function `kernel::k_screen::putc(char)':
/video.cpp:138: undefined reference to `kernel::k_screen::width'
/video.cpp:138: undefined reference to `kernel::k_screen::csr_x'
/video.cpp:141: undefined reference to `kernel::k_screen::csr_x'
/video.cpp:141: undefined reference to `kernel::k_screen::csr_x'
/video.cpp:141: undefined reference to `kernel::k_screen::csr_x'
/video.cpp:144: undefined reference to `kernel::k_screen::mem_addr'
/video.cpp:144: undefined reference to `kernel::k_screen::csr_y'
/video.cpp:144: undefined reference to `kernel::k_screen::width'
/video.cpp:144: undefined reference to `kernel::k_screen::csr_x'
/video.cpp:144: undefined reference to `kernel::k_screen::color'
/video.cpp:147: undefined reference to `kernel::k_screen::csr_x'
/video.cpp:147: undefined reference to `kernel::k_screen::width'
/video.cpp:149: undefined reference to `kernel::k_screen::csr_x'
/video.cpp:150: undefined reference to `kernel::k_screen::csr_y'
/video.cpp:150: undefined reference to `kernel::k_screen::csr_y'
/video.cpp:152: undefined reference to `kernel::k_screen::csr_y'
/video.cpp:152: undefined reference to `kernel::k_screen::width'
/video.cpp:152: undefined reference to `kernel::k_screen::height'
/video.cpp:152: undefined reference to `kernel::k_screen::width'
/video.cpp:154: undefined reference to `kernel::k_screen::mem_addr'
/video.cpp:155: undefined reference to `kernel::k_screen::mem_addr'
/video.cpp:155: undefined reference to `kernel::k_screen::width'
/video.cpp:156: undefined reference to `kernel::k_screen::mem_addr'
/video.cpp:156: undefined reference to `kernel::k_screen::height'
/video.cpp:156: undefined reference to `kernel::k_screen::width'
/video.cpp:164: undefined reference to `kernel::k_screen::color'
/video.cpp:161: undefined reference to `kernel::k_screen::mem_addr'
/video.cpp:161: undefined reference to `kernel::k_screen::height'
/video.cpp:161: undefined reference to `kernel::k_screen::width'
/video.cpp:166: undefined reference to `kernel::k_screen::csr_y'
/video.cpp:166: undefined reference to `kernel::k_screen::csr_y'
src/video.o: In function `kernel::k_screen::setBase(unsigned char)':
/video.cpp:172: undefined reference to `kernel::k_screen::base'
make: *** [pri.bin] Error 1