• Advertisement
Sign in to follow this  

trivial borland c++ linker error (with SDL)

This topic is 4679 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Error: Unresolved external '_SDL_GetError' referenced from C:\DOCUMENTS AND SETTINGS\DDONNELLY\DESKTOP\SDL\SDL_WIN32_MAIN.OBJ I'm using Borland C++ 5.5 command line tools and I'm trying to do SDL. The instructions for linking with SDL are right here in the FAQ: SDL with Borland C++ I've made an import library with implib as said and I've tried other combinations of -a (names with underscore) and -c (case sensitive). I've put SDL.lib in c:\borland\lib and i've also deleted SDL_main.lib since we have to care for that our selves with SDL_main.c (or in my case SDL_win32_main.c). The SDL header files are in c:\borland\include\SDL. I've done all of what I think is needed and my build environment looks like: (where > denotes what I actually enter) > bcc32.exe -I%B_INC% -L%B_LIB% -c -tW -DWIN32 test1.cpp SDL_win32_main.c B_INC = c:\borland\bcc55\include B_LIB = c:\borland\bcc55\lib > ilink32.exe -Lc:\borland\bcc55\lib -aa -Tpe -c sdl.lib import32.lib c0w32.obj cw32.lib test1.obj SDL_win32_main.obj (-Lc:\borland\bcc55\lib seems to be sufficient for object files as well) The order of the files in the above commands doesn't seem to matter(switching SDL_win32_main.c with test1.cpp and putting the object files both ahead and before the other import libs didn't matter. the output of ilink32 is: Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland Error: Unresolved external '_SDL_GetError' referenced from C:\DOCUMENTS AND SETTINGS\DDONNELLY\DESKTOP\SDL\SDL_WIN32_MAIN.OBJ test1.cpp is nothing special:
#include <stdlib.h>
#include <SDL/SDL.h>

SDL_Surface *screen;

void render();

int main(int argc, char *argv[])
{
   if(SDL_Init(SDL_INIT_VIDEO) < 0)
   {
      fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
      exit(1);
   }

   // register SDL_quit to be called at exit, so things are cleaned up
   atexit(SDL_Quit);

   // create 640x480 with 32-bit pxls
   screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);

   // return error on fail
   if(screen == NULL)
   {
      fprintf(stderr, "Unable to set 640x480 video: %s\n", SDL_GetError());
      exit(1);
   }

   // main loop
   while(1)
   {
      render();

      SDL_Event event;

      while(SDL_PollEvent(&event))
      {
         switch(event.type)
         {
            case SDL_KEYUP:
               if(event.key.keysym.sym == SDLK_ESCAPE)
                  return 0;
               break;
            case SDL_QUIT:
               return 0;
            default:
               break;
         }
      }
   }

   // return 0;      // unreachable
}

void render()
{
   // lock surface if need be
   if(SDL_MUSTLOCK(screen))
      if(SDL_LockSurface(screen) < 0)
         return;            // couldn't lock

   // time in millis
   int tick = SDL_GetTicks();

   int i, j, yofs, ofs;

   // draw screen;
   yofs = 0;
   for(i=0; i<480; i++)
   {
      for(j=0,ofs=yofs; j<640; j++,ofs++)
      {
         ((unsigned int*)screen->pixels)[ofs] = i*i + j*j + tick;
      }
      yofs += screen->pitch /4;
   }

   // unlock if need be
   if(SDL_MUSTLOCK(screen))
      SDL_UnlockSurface(screen);

   // tell SDL to update screen
   SDL_UpdateRect(screen,0,0,640,480);
}



SDL_win32_main.c might help:
/*
    SDL_main.c, placed in the public domain by Sam Lantinga  4/13/98

    The WinMain function -- calls your program's main() function
*/

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>

#include <windows.h>
#include <malloc.h>         /* For _alloca() */

#ifdef _WIN32_WCE
# define DIR_SEPERATOR TEXT("\\")
# undef _getcwd
# define _getcwd(str,len)   wcscpy(str,TEXT(""))
# define setbuf(f,b)
# define setvbuf(w,x,y,z)
# define fopen      _wfopen
# define freopen   _wfreopen
# define remove(x)   DeleteFile(x)
# define strcat      wcscat
#else
# define DIR_SEPERATOR TEXT("/")
# include <direct.h>
#endif

/* Include the SDL main definition header */
#include "SDL\SDL.h"
#include "SDL\SDL_main.h"

#ifdef main
# ifndef _WIN32_WCE_EMULATION
#  undef main
# endif /* _WIN32_WCE_EMULATION */
#endif /* main */

/* The standard output files */
#define STDOUT_FILE   TEXT("stdout.txt")
#define STDERR_FILE   TEXT("stderr.txt")

#ifndef NO_STDIO_REDIRECT
# ifdef _WIN32_WCE
  static wchar_t stdoutPath[MAX_PATH];
  static wchar_t stderrPath[MAX_PATH];
# else
  static char stdoutPath[MAX_PATH];
  static char stderrPath[MAX_PATH];
# endif
#endif

#if defined(_WIN32_WCE) && _WIN32_WCE < 300
/* seems to be undefined in Win CE although in online help */
#define isspace(a) (((CHAR)a == ' ') || ((CHAR)a == '\t'))

/* seems to be undefined in Win CE although in online help */
char *strrchr(char *str, int c)
{
   char *p;

   /* Skip to the end of the string */
   p=str;
   while (*p)
      p++;

   /* Look for the given character */
   while ( (p >= str) && (*p != (CHAR)c) )
      p--;

   /* Return NULL if character not found */
   if ( p < str ) {
      p = NULL;
   }
   return p;
}
#endif /* _WIN32_WCE < 300 */

/* Parse a command line buffer into arguments */
static int ParseCommandLine(char *cmdline, char **argv)
{
   char *bufp;
   int argc;

   argc = 0;
   for ( bufp = cmdline; *bufp; ) {
      /* Skip leading whitespace */
      while ( isspace(*bufp) ) {
         ++bufp;
      }
      /* Skip over argument */
      if ( *bufp == '"' ) {
         ++bufp;
         if ( *bufp ) {
            if ( argv ) {
               argv[argc] = bufp;
            }
            ++argc;
         }
         /* Skip over word */
         while ( *bufp && (*bufp != '"') ) {
            ++bufp;
         }
      } else {
         if ( *bufp ) {
            if ( argv ) {
               argv[argc] = bufp;
            }
            ++argc;
         }
         /* Skip over word */
         while ( *bufp && ! isspace(*bufp) ) {
            ++bufp;
         }
      }
      if ( *bufp ) {
         if ( argv ) {
            *bufp = '\0';
         }
         ++bufp;
      }
   }
   if ( argv ) {
      argv[argc] = NULL;
   }
   return(argc);
}

/* Show an error message */
static void ShowError(const char *title, const char *message)
{
/* If USE_MESSAGEBOX is defined, you need to link with user32.lib */
#ifdef USE_MESSAGEBOX
   MessageBox(NULL, message, title, MB_ICONEXCLAMATION|MB_OK);
#else
   fprintf(stderr, "%s: %s\n", title, message);
#endif
}

/* Pop up an out of memory message, returns to Windows */
static BOOL OutOfMemory(void)
{
   ShowError("Fatal Error", "Out of memory - aborting");
   return FALSE;
}

/* Remove the output files if there was no output written */
static void __cdecl cleanup_output(void)
{
#ifndef NO_STDIO_REDIRECT
   FILE *file;
   int empty;
#endif

   /* Flush the output in case anything is queued */
   fclose(stdout);
   fclose(stderr);

#ifndef NO_STDIO_REDIRECT
   /* See if the files have any output in them */
   if ( stdoutPath[0] ) {
      file = fopen(stdoutPath, TEXT("rb"));
      if ( file ) {
         empty = (fgetc(file) == EOF) ? 1 : 0;
         fclose(file);
         if ( empty ) {
            remove(stdoutPath);
         }
      }
   }
   if ( stderrPath[0] ) {
      file = fopen(stderrPath, TEXT("rb"));
      if ( file ) {
         empty = (fgetc(file) == EOF) ? 1 : 0;
         fclose(file);
         if ( empty ) {
            remove(stderrPath);
         }
      }
   }
#endif
}

#if defined(_MSC_VER) && !defined(_WIN32_WCE)
/* The VC++ compiler needs main defined */
#define console_main main
#endif

/* This is where execution begins [console apps] */
int console_main(int argc, char *argv[])
{
   int n;
   char *bufp, *appname;

   /* Get the class name from argv[0] */
   appname = argv[0];
   if ( (bufp=strrchr(argv[0], '\\')) != NULL ) {
      appname = bufp+1;
   } else
   if ( (bufp=strrchr(argv[0], '/')) != NULL ) {
      appname = bufp+1;
   }

   if ( (bufp=strrchr(appname, '.')) == NULL )
      n = strlen(appname);
   else
      n = (bufp-appname);

   bufp = (char *)alloca(n+1);
   if ( bufp == NULL ) {
      return OutOfMemory();
   }
   strncpy(bufp, appname, n);
   bufp[n] = '\0';
   appname = bufp;

   /* Load SDL dynamic link library */
   if ( SDL_Init(SDL_INIT_NOPARACHUTE) < 0 ) {
      ShowError("WinMain() error", SDL_GetError());
      return(FALSE);
   }
   atexit(cleanup_output);
   atexit(SDL_Quit);

#ifndef DISABLE_VIDEO
#if 0
   /* Create and register our class *
      DJM: If we do this here, the user nevers gets a chance to
      putenv(SDL_WINDOWID).  This is already called later by
      the (DIB|DX5)_CreateWindow function, so it should be
      safe to comment it out here.
   if ( SDL_RegisterApp(appname, CS_BYTEALIGNCLIENT,
                        GetModuleHandle(NULL)) < 0 ) {
      ShowError("WinMain() error", SDL_GetError());
      exit(1);
   }*/
#else
   /* Sam:
      We still need to pass in the application handle so that
      DirectInput will initialize properly when SDL_RegisterApp()
      is called later in the video initialization.
    */
   SDL_SetModuleHandle(GetModuleHandle(NULL));
#endif /* 0 */
#endif /* !DISABLE_VIDEO */

   /* Run the application main() code */
   SDL_main(argc, argv);

   /* Exit cleanly, calling atexit() functions */
   exit(0);

   /* Hush little compiler, don't you cry... */
   return(0);
}

/* This is where execution begins [windowed apps] */
#ifdef _WIN32_WCE
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPWSTR szCmdLine, int sw)
#else
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
#endif
{
   HINSTANCE handle;
   char **argv;
   int argc;
   char *cmdline;
#ifdef _WIN32_WCE
   wchar_t *bufp;
   int nLen;
#else
   char *bufp;
#endif
#ifndef NO_STDIO_REDIRECT
   FILE *newfp;
#endif

   /* Start up DDHELP.EXE before opening any files, so DDHELP doesn't
      keep them open.  This is a hack.. hopefully it will be fixed
      someday.  DDHELP.EXE starts up the first time DDRAW.DLL is loaded.
    */
   handle = LoadLibrary(TEXT("DDRAW.DLL"));
   if ( handle != NULL ) {
      FreeLibrary(handle);
   }

#ifndef NO_STDIO_REDIRECT
   _getcwd( stdoutPath, sizeof( stdoutPath ) );
   strcat( stdoutPath, DIR_SEPERATOR STDOUT_FILE );

   /* Redirect standard input and standard output */
   newfp = freopen(stdoutPath, TEXT("w"), stdout);

#ifndef _WIN32_WCE
   if ( newfp == NULL ) {   /* This happens on NT */
#if !defined(stdout)
      stdout = fopen(stdoutPath, TEXT("w"));
#else
      newfp = fopen(stdoutPath, TEXT("w"));
      if ( newfp ) {
         *stdout = *newfp;
      }
#endif
   }
#endif /* _WIN32_WCE */

   _getcwd( stderrPath, sizeof( stderrPath ) );
   strcat( stderrPath, DIR_SEPERATOR STDERR_FILE );

   newfp = freopen(stderrPath, TEXT("w"), stderr);
#ifndef _WIN32_WCE
   if ( newfp == NULL ) {   /* This happens on NT */
#if !defined(stderr)
      stderr = fopen(stderrPath, TEXT("w"));
#else
      newfp = fopen(stderrPath, TEXT("w"));
      if ( newfp ) {
         *stderr = *newfp;
      }
#endif
   }
#endif /* _WIN32_WCE */

   setvbuf(stdout, NULL, _IOLBF, BUFSIZ);   /* Line buffered */
   setbuf(stderr, NULL);         /* No buffering */
#endif /* !NO_STDIO_REDIRECT */

#ifdef _WIN32_WCE
   nLen = wcslen(szCmdLine)+128+1;
   bufp = (wchar_t *)alloca(nLen*2);
   wcscpy (bufp, TEXT("\""));
   GetModuleFileName(NULL, bufp+1, 128-3);
   wcscpy (bufp+wcslen(bufp), TEXT("\" "));
   wcsncpy(bufp+wcslen(bufp), szCmdLine,nLen-wcslen(bufp));
   nLen = wcslen(bufp)+1;
   cmdline = (char *)alloca(nLen);
   if ( cmdline == NULL ) {
      return OutOfMemory();
   }
   WideCharToMultiByte(CP_ACP, 0, bufp, -1, cmdline, nLen, NULL, NULL);
#else
   /* Grab the command line (use alloca() on Windows) */
   bufp = GetCommandLine();
   cmdline = (char *)alloca(strlen(bufp)+1);
   if ( cmdline == NULL ) {
      return OutOfMemory();
   }
   strcpy(cmdline, bufp);
#endif

   /* Parse it into argv and argc */
   argc = ParseCommandLine(cmdline, NULL);
   argv = (char **)alloca((argc+1)*(sizeof *argv));
   if ( argv == NULL ) {
      return OutOfMemory();
   }
   ParseCommandLine(cmdline, argv);

   /* Run the main program (after a little SDL initialization) */
   return(console_main(argc, argv));
}


[Edited by - Gaal Dormick on April 26, 2005 8:53:18 PM]

Share this post


Link to post
Share on other sites
Advertisement
Okay, first off, where are your commas in the call to ilink32?

Second, it says that for 1.2.5 and newer you should look at Borland.html in the source, does it say the same thing as the instructions you linked to?

Third, aw screw it, the problems I see should be unrelated to your error, so let me look back in time through my files(I quit using SDL, I now use glfw, http://glfw.sourceforge.net/ and have found it to be the most easily compiled and most easily thing used ever).

http://home.earthlink.net/~aaron_ogden/sdl.mak
Here's a file to help you out, it's the one I used to use, minus references to personal projects. Note that I have not really edited it all that much so while it sounds like I'm giving advice, I just happen to write everything as if I myself don't know how to use them since I often go weeks without modifying documents.

Fourth, bcc32.cfg and ilink32.cfg are your friends, use them, ask me how if you don't know.

Share this post


Link to post
Share on other sites
What I linked to says this about Borland.html in the SDL source:
Quote:

Martin Bickel writes:
For both Watcom C/C++ and Borland C/C++ the compiler option that makes enums having the size of an int must be enabled. This is "-b" for Borland C/C++ and "-ei" for Watcom C/C++ (v11).


I assumed that this wouldn't apply to me with my simple test, but I'll enable those options and try it again.

That wasn't the problem. I'll look into GLFW, looks promising, but I still need to find a solution to this problem. If I don't in a week I'll switch to the free VC++ compiler + SDL.

Share this post


Link to post
Share on other sites
Quote:
Original post by RolandofGilead
Okay, first off, where are your commas in the call to ilink32?

To see what I mean, just type in ilink32 in the console and look at the line that starts with "Syntax: ILINK32..."

sdl.mak
clickified for your convenience, just try it, instructions are within

Share this post


Link to post
Share on other sites
Okay, I'm going to see what you mean, but in that sdl.mak you linked to, why are their extra commas given: "....,,....,,"?

Share this post


Link to post
Share on other sites
Quote:

Link the.obj files together using ILINK32 with the following options:
-aa (Create windows app, sounds redundant, but...)
-Tpe (Target = windows exe)
-c (case sensitive linking, may be the default...)
and the following additional files (order is important)

* sdl.lib (created in step 1)
* import32.lib
* c0w32.obj
* cw32.lib


Okay, it says "order is important" and then lists the files. So I just assumed we're all reading from top to bottom. But this might not be the case, so I'm going to try grouping them by type as ilink32 usage requires. Please inform me of any pitfalls I am going to encounter :D

edit: okay, I see the order matches what you have in sdl.make, and they're all grouped within the libfiles commas. What makes c0w32.obj a "lib" file instead of an "obj" file which I assumed from its extension?

Share this post


Link to post
Share on other sites
I'm using this:
ilink32.exe -Lc:\borland\bcc55\lib -aa -Tpe -c SDL_win32_main.obj %1.obj, %1.exe,, sdl.lib import32.lib c0w32.obj cw32.lib,,

getting the exact same error.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Why is your error '_SDL_GetError' instead of 'SDL_GetError'?

Share this post


Link to post
Share on other sites
The naming convention of the compiler I'm guessing. It outputs object files with "_" appendended to the front. Microsft's compilers do something simpilar and also append "@16" meaning 16 bytes pushed onto the stack when it's called (forgot what level this is done at - the final dll, or import lib...). Yeah, I belive there should be a standard for linking code. I had a hell of a time getting things going with nasm. Don't take any of this as correct - I haven't been worked with linkers in several months (took a break with Java).

Share this post


Link to post
Share on other sites
Gaal: correct, I'm unaware of any compiler that does NOT prepend an underscore to a C symbol, although I'm (fairly) sure they exist. I vaugely remember GCC maybe having an option to turn this off. Being a pretty defacto (or official?) standard I wouldn't recommend that though.

If you want my 2 cents, I'd switch over to Cygwin or MinGW, both of which are windows ports of GNU software. If you want a free IDE as well I'd get Eclipse, a Java based IDE designed for developing Java, but is great for developing in C/C++ if you install the CDT plugin, and runs completely seamlessly atop a cygwin installation (and with a few hiccups atop MinGW I've found).

Personally, I chose MinGW, as by default Cygwin links in some GPLed library stuff (which is disableable with an extra flag, but I hate extra flags :P). Getting Eclipse to work with it was a simple matter of creating a copy of mingw32-make.exe as make.exe so I wouldn't have to change the make command for every managed make C/C++ project in eclipse, adding C:\MinGW\bin to %PATH%, and ignoring the fact that Eclipse can't find the "rm" command (the GNU/Linux version of "del").

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
The error message implies that the symbol is not present in your SDL.lib. So, your SDL.lib is most likely corrupt. Off hand I can only imagine a few typical causes for this:

1. You fouled up the order of arguments in implib and created a junk 1KB SDL.lib file. This is an easy mistake but it does not fit your problem. You should be missing more symbols and more errors would be generated if this were the case.

2. The SDL.dll from which you generated the SDL.lib was corrupt or compiled without SDL_GetError. You could try compiling SDL.dll yourself with freebcc. The latest SDL (1.2.8) will not compile on freebcc without some slight changes. You need to add cpuinfo.c to the SDL.mak and add a couple typecasts in SDL_dibevents.c and SDL_dx5events.c.

The page you linked to in the OP also has a link to the help files for this compiler. Use those help files to figure out why ilink has those extra commas.

Share this post


Link to post
Share on other sites
I ran a dumpbin /exports on SDL.dll and SDL_GetError is there. I'll look into MingW. I don't want Eclipse though - ugh. Complex, graphical IDE's are not my bag. Anyway, I tried compiling something with borland that is easily compiled with VC++ and got some nonsense errors. It's going out the door.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement