I'm need help to understand how to fix this linker error:
POLINK: error: Unresolved external symbol '__imp__GetAsyncKeyState@4'.
POLINK: fatal error: 1 unresolved external(s).
*** Error code: 1 ***
I was trying to build this as a console project with Windows extensions and char's set to unsigned.
Thanks for your help.
In this code:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
/* ------------------
* Macros & Constants
*/
/* validate a paddle id */
#define VALID_PAD_ID(id) ( (id) > PAD_ID_INVALID && (id) < MAX_PAD_IDS )
/* check if a Win32 API virtual-key is pressed */
#define VKEY_IS_PRESSED(vk) ( GetAsyncKeyState(vk) & 0x8000 )
/* paddles related constants */
enum {
/* paddle ids */
PAD_ID_INVALID = -1,
PAD_ID_1 = 0,
PAD_ID_2 = 1,
MAX_PAD_IDS,
/* positional offsets */
PAD1_X_OFFSET = 10,
PAD1_Y_OFFSET = 10,
PAD2_X_OFFSET = 30,
PAD2_Y_OFFSET = 10,
/* positional bounndaries */
PAD_UPLIMIT = 5,
PAD_DNLIMIT = 23
};
/* Win32 API virtual-keys to be handled:
http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx
*/
enum VKey {
VKEY_ESC= VK_ESCAPE,
VKEY_W = 0x57,
VKEY_S = 0x53,
VKEY_UP = VK_UP,
VKEY_DN = VK_DOWN
};
/* ------------
* Custom Types
*/
/* struct describing a paddle */
typedef struct Paddle {
int id;
/* positional data */
COORD top;
COORD upmid; /* upper middle */
COORD mid; /* middle */
COORD lomid; /* lower middle */
COORD bot; /* bottom */
}Paddle;
/* struct describing the game box (excluding paddles) */
typedef struct Gamebox {
COORD hline[44]; /* horizontal line */
COORD hlineFar[44];
COORD vline[21]; /* vertical line */
COORD vlineFar[21];
COORD vlineDashed[10];
}Gamebox;
/* struct describing the whole game (may be useful to pass it as user-data in callbacks) */
typedef struct Game {
Gamebox box;
Paddle pads[MAX_PAD_IDS]; /* array of paddles */
}Game;
/* ----------------
* Global Variables
*/
/* all paddles data (this could be loaded from a file instead) */
Paddle g_paddlesDatapool[MAX_PAD_IDS] = {
{ /* 1st paddle */
PAD_ID_1, /* id */
{2 + PAD1_X_OFFSET, 2 + PAD1_Y_OFFSET}, /* top */
{2 + PAD1_X_OFFSET, 3 + PAD1_Y_OFFSET}, /* upper middle */
{2 + PAD1_X_OFFSET, 4 + PAD1_Y_OFFSET}, /* middle */
{2 + PAD1_X_OFFSET, 5 + PAD1_Y_OFFSET}, /* lower middle */
{2 + PAD1_X_OFFSET, 6 + PAD1_Y_OFFSET} /* bottom */
},
{ /* 2nd paddle */
PAD_ID_2, /* id */
{16 + PAD2_X_OFFSET, 2 + PAD2_Y_OFFSET}, /* top */
{16 + PAD2_X_OFFSET, 3 + PAD2_Y_OFFSET}, /* upper middle */
{16 + PAD2_X_OFFSET, 4 + PAD2_Y_OFFSET}, /* middle */
{16 + PAD2_X_OFFSET, 5 + PAD2_Y_OFFSET}, /* lower middle */
{16 + PAD2_X_OFFSET, 6 + PAD2_Y_OFFSET} /* bottom */
}
};
/* -------------------
* Function Prototypes
*/
static void gamebox_init( Gamebox * );
static void gamebox_draw( const Gamebox * );
static void paddle_init( Paddle *paddle, int id, Paddle datapool[] );
static void paddle_draw( const Paddle *);
static void paddle_undraw( const Paddle * );
static void paddle_up_draw( Paddle * );
static void paddle_dn_draw( Paddle * );
static void game_loop( Game *game, int msleep );
static void cls( HANDLE hConsole );
static void gotoxy( int x, int y );
/* -------------------
* Function Definitions
*/
/* ----------------------------------------------------- */
int main( void )
{
Game game;
int msleep = 20; /* delay after each game-loop iteration, in msecs */
gamebox_init( &game.box );
paddle_init( &game.pads[0], PAD_ID_1, g_paddlesDatapool );
paddle_init( &game.pads[1], PAD_ID_2, g_paddlesDatapool );
gamebox_draw( &game.box );
paddle_draw( &game.pads[0] );
paddle_draw( &game.pads[1] );
game_loop( &game, msleep );
exit( EXIT_SUCCESS );
}
/*
* Gamebox functions
*/
/* ----------------------------------------------------- */
static void gamebox_init( Gamebox *box )
{
int i=0;
int offsetDashedLn = 0;
for (i=0; i < 43; i++)
{
box->hline[i].X = 8 + i;
box->hline[i].Y = 4;
box->hlineFar[i].X = 8 + i;
box->hlineFar[i].Y = 23;
}
for (i=0; i < 20; i++)
{
box->vline[i].X = 8;
box->vline[i].Y = 4 + i;
box->vlineFar[i].X = 50;
box->vlineFar[i].Y = 4 + i;
}
for (i=0; i < 9; i++)
{
box->vlineDashed[i].X = 28;
box->vlineDashed[i].Y = 6 + offsetDashedLn;
offsetDashedLn += 2;
}
return;
}
/* ----------------------------------------------------- */
static void gamebox_draw( const Gamebox *box )
{
int i;
HANDLE hStdout;
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
cls(hStdout);
/* horizontal lines */
for (i=0; i < 43; i++ )
{
gotoxy( box->hline[i].X, box->hline[i].Y );
putchar('U');
gotoxy( box->hlineFar[i].X, box->hlineFar[i].Y );
putchar('U');
}
/* vertical lines */
for (i=0; i < 20; i++)
{
gotoxy( box->vline[i].X, box->vline[i].Y );
putchar('U');
gotoxy( box->vlineFar[i].X, box->vlineFar[i].Y );
putchar('U');
}
/* vertical dashed line */
for (i=0; i < 9; i++)
{
gotoxy( box->vlineDashed[0+i].X, box->vlineDashed[0+i].Y);
putchar('±'); //ascii 241
}
return;
}
/*
* Paddles functions
*/
/* ----------------------------------------------------- */
static void paddle_init( Paddle *pad, int id, Paddle datapool[] )
{
if ( !pad )
return;
/* start fresh */
memset( pad, 0, sizeof(*pad) );
if ( !VALID_PAD_ID(id) ) {
pad->id = PAD_ID_INVALID;
}
else {
memcpy( pad, &datapool[id], sizeof(*pad) );
}
return;
}
/* ----------------------------------------------------- */
static void paddle_draw( const Paddle *pad )
{
if ( !pad )
return;
if ( VALID_PAD_ID(pad->id) )
{
gotoxy( pad->top.X, pad->top.Y );
putchar('U');
gotoxy( pad->upmid.X, pad->upmid.Y );
putchar('U');
gotoxy( pad->mid.X, pad->mid.Y );
putchar('U');
gotoxy( pad->lomid.X, pad->lomid.Y );
putchar('U');
gotoxy( pad->bot.X, pad->bot.Y );
}
gotoxy(0,0);
return;
}
/* ----------------------------------------------------- */
static void paddle_undraw( const Paddle *pad )
{
if ( !pad )
return;
if ( VALID_PAD_ID(pad->id) )
{
gotoxy( pad->top.X, pad->top.Y );
putchar(' ');
gotoxy( pad->upmid.X, pad->upmid.Y );
putchar(' ');
gotoxy( pad->mid.X, pad->mid.Y );
putchar(' ');
gotoxy( pad->lomid.X, pad->lomid.Y );
putchar(' ');
gotoxy( pad->bot.X, pad->bot.Y );
}
gotoxy(0,0);
return;
}
/* ----------------------------------------------------- */
static void paddle_up_draw( Paddle *pad )
{
if ( !pad )
return;
if ( PAD_UPLIMIT != pad->top.Y )
{
paddle_undraw( pad );
pad->bot.Y--;
pad->lomid.Y--;
pad->mid.Y--;
pad->upmid.Y--;
pad->top.Y--;
paddle_draw( pad );
}
return;
}
/* ----------------------------------------------------- */
static void paddle_dn_draw( Paddle *pad )
{
if ( !pad )
return;
if ( PAD_DNLIMIT != pad->bot.Y )
{
paddle_undraw( pad );
pad->bot.Y++;
pad->lomid.Y++;
pad->mid.Y++;
pad->upmid.Y++;
pad->top.Y++;
paddle_draw( pad );
}
return;
}
/*
* Game functions
*/
/* ----------------------------------------------------- */
static void game_loop( Game *game, int msleep )
{
for (;;)
{
if ( VKEY_IS_PRESSED(VKEY_ESC) )
break;
if ( VKEY_IS_PRESSED(VKEY_W) ) {
paddle_up_draw( &game->pads[0] );
}
if ( VKEY_IS_PRESSED(VKEY_S) ) {
paddle_dn_draw( &game->pads[0] );
}
if ( VKEY_IS_PRESSED(VK_UP) ) {
paddle_up_draw( &game->pads[1] );
}
if ( VKEY_IS_PRESSED(VKEY_DN) ) {
paddle_dn_draw( &game->pads[1] );
}
Sleep(msleep);
}
return;
}
/*
* Misc functions
*/
/* -----------------------------------------------------
* Credit for this function goes to Microsoft's website's help section here:
* http://msdn.microsoft.com/en-us/library/windows/desktop/ms682022%28v=vs.85%29.aspx
*/
static void cls( HANDLE hConsole )
{
COORD coordScreen = { 0, 0 }; /* home for the cursor */
DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize;
/* Get the number of character cells in the current buffer. */
if ( !GetConsoleScreenBufferInfo(hConsole, &csbi) )
{
return;
}
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
/* Fill the entire screen with blanks. */
if (
!FillConsoleOutputCharacter(
hConsole, /* Handle to console screen buffer */
(TCHAR) ' ', /* Character to write to the buffer */
dwConSize, /* Number of cells to write */
coordScreen, /* Coordinates of first cell */
&cCharsWritten ) /* Receive number of characters written */
){
return;
}
/* Get the current text attribute. */
if ( !GetConsoleScreenBufferInfo(hConsole, &csbi) )
{
return;
}
/* Set the buffer's attributes accordingly. */
if (
!FillConsoleOutputAttribute(
hConsole, /* Handle to console screen buffer */
csbi.wAttributes, /* Character attributes to use */
dwConSize, /* Number of cells to set attribute */
coordScreen, /* Coordinates of first cell */
&cCharsWritten ) /* Receive number of characters written */
){
return;
}
/* Put the cursor at its home coordinates. */
SetConsoleCursorPosition( hConsole, coordScreen );
}
/* ----------------------------------------------------- */
static void gotoxy(int x, int y)
{
COORD temp;
temp.X = x;
temp.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), temp);
}