[gambit-list] Using compile-file and load on Windows

Edward Tate cmalune at gmail.com
Thu Apr 17 12:47:27 EDT 2008


I've been having problems recently whilst trying to compile and load C
files into gambit-c dynamically. Originally I was using gsc & gcc at
the command prompt to statically link all of my files, but this got
cumbersome as the number of c files grew.

I have a file called "_Vector.ss" which binds to the C files
"Vector.h" and "Vector.c", which works fine whilst using (compile-file
"_Vector.ss") and then (load "_Vector").

The problems came when I tried to do this with a file "_W32Window.ss"
which binds to the C files "W32Window.h" and "W32Window.c", which
requires support from external libraries.

The error I get is this (a few linker errors):
C:\DOCUME~1\malune\LOCALS~1\Temp/ccMXbaaa.o:_W32Window.c:(.text+0x6db):
undefined reference to `SwapBuffers at 4'
C:\DOCUME~1\malune\LOCALS~1\Temp/ccMXbaaa.o:_W32Window.c:(.text+0x746):
undefined reference to `ChoosePixelFormat at 8'
C:\DOCUME~1\malune\LOCALS~1\Temp/ccMXbaaa.o:_W32Window.c:(.text+0x775):
undefined reference to `SetPixelFormat at 12'
C:\DOCUME~1\malune\LOCALS~1\Temp/ccMXbaaa.o:_W32Window.c:(.text+0x794):
undefined reference to `wglCreateContext at 4'
C:\DOCUME~1\malune\LOCALS~1\Temp/ccMXbaaa.o:_W32Window.c:(.text+0x7bd):
undefined reference to `wglMakeCurrent at 8'
C:\DOCUME~1\malune\LOCALS~1\Temp/ccMXbaaa.o:_W32Window.c:(.text+0x7f4):
undefined reference to `wglMakeCurrent at 8'
C:\DOCUME~1\malune\LOCALS~1\Temp/ccMXbaaa.o:_W32Window.c:(.text+0x80b):
undefined reference to `wglDeleteContext at 4'
collect2: ld returned 1 exit status

I've tried modifying gsc-cc-o.bat so that the libs included were the
same as the gcc that worked under the command line: "-mno-cygwin
-lmingw32 -lgdi32 -lopengl32 -lglu32 -lgambc". But this did not change
the outcome of the problem.

So basically I can link things statically without any problems because
I'm calling gcc manually, but when I start to dynamically link things
go wrong. Am I missing something obvious? Any thoughts would be highly
appreciated.

Thanks,
Edward Tate

PS: Here are the files:

_W32Window.ss:

(c-declare "#include \"W32Window.h\"")
(c-declare "#include \"W32Window.c\"")

(c-define-type SW32Window (struct "SW32Window"))
(c-define-type SW32Window* (pointer SW32Window))

(define wnd-create!
  (c-lambda () void "wndCreate"))

(define wnd-destroy!
  (c-lambda () void "wndDestroy"))

(define wnd-create-instance!
  (c-lambda (char-string) int "wndCreateInstance"))

(define wnd-set!
  (c-lambda (int int int int) void "wndSet"))

(define wnd-handle-message
  (c-lambda () int "wndHandleMessage"))

;(define wnd-swap-buffers
;  (c-lambda () void "wndSwapBuffers"))

(define vk-up
  (c-lambda () int "vkUp"))
(define vk-down
  (c-lambda () int "vkDown"))
(define vk-left
  (c-lambda () int "vkLeft"))
(define vk-right
  (c-lambda () int "vkRight"))
(define vk-escape
  (c-lambda () int "vkEscape"))


W32Window.h:

//---------------------------------------------------------------------------
// Lib Name: Win32 Window
// Author: Deweta
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
// W32Window Header
//---------------------------------------------------------------------------
#include <windows.h>
#define WIN32_LEAN_AND_MEAN

#include <GL/gl.h>
#include <GL/glu.h>

#include <stdio.h>

//---------------------------------------------------------------------------
// W32Window Definitions
//---------------------------------------------------------------------------
enum {
  RENDERER_W32     = 0,
  RENDERER_GL      = 1,
  RENDERER_D3D     = 2
};

struct SGLContext
{
  GLuint               _pixelFormat;
  HGLRC                _hRC;
};

PIXELFORMATDESCRIPTOR pfd =
  {
    sizeof(PIXELFORMATDESCRIPTOR),
    1,
    PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
    PFD_TYPE_RGBA,
    16,
    0, 0, 0, 0, 0, 0,
    0,
    0,
    0,
    0, 0, 0, 0,
    16,
    0,
    0,
    PFD_MAIN_PLANE,
    0,
    0, 0, 0
  };

//struct SD3DContext
//{
//  D3DPRESENT_PARAMETERS   _D3DPP;
//  LPDIRECT3D9             _pD3D;
//  LPDIRECT3DDEVICE9       _pD3DDevice;
//};

struct SW32Window
{
  // Used for GL/D3D window
  void                 *_renderContext;

  // Device
  DEVMODE              _dmScreenSettings;
  HDC                  _hDC;

  // Window
  HFONT                _defaultFont;
  DWORD                _dwStyle;
  DWORD                _dwExStyle;
  WNDCLASS             _wc;
  RECT                 _rect;
  HWND                 _hWnd;
  HINSTANCE            _hInstance;

  // Window Flags
  int                 _isActive;
  int                 _isFullscreen;

  // Event
  MSG                  _eventMsg;

  // Keyboard
  int                  _keys[256];
};

struct SW32Window *this;

//---------------------------------------------------------------------------
// W32Window Inline Functions
//---------------------------------------------------------------------------

// W32 wndProc
LRESULT CALLBACK wndProc0(struct SW32Window *this,
			  HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK wndProc1(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam);

// Keyboard
int vkUp(void);
int vkDown(void);
int vkLeft(void);
int vkRight(void);
int vkEscape(void);

//---------------------------------------------------------------------------
// W32Window Prototypes
//---------------------------------------------------------------------------

// Constructor
void wndCreate(void);

// Destructor
void wndDestroy(void);

// Event
int wndHandleMessage(void);

//
int wndCreateInstance(const char *title);
int wndDestroyInstance(void);

void wndSet(int w, int h, int bpp, int fs);

//
void wndSwapBuffers(void);

// GL Context
int wndGLCreate(const char *title);
int wndGLDestroy(void);

int wndGLCreateContext(void);
int wndGLDestroyContext(void);


W32Window.c:

int vkUp(void) { return this->_keys[VK_UP]; }
int vkDown(void) { return this->_keys[VK_DOWN]; }
int vkLeft(void) { return this->_keys[VK_LEFT]; }
int vkRight(void) { return this->_keys[VK_RIGHT]; }
int vkEscape(void) { return this->_keys[VK_ESCAPE]; }

// Constructor
void wndCreate(void) {
  this = malloc(sizeof(struct SW32Window));
  this->_renderContext = NULL;
}

// Destructor
void wndDestroy(void) {
  if(this->_renderContext)
    free(this->_renderContext);
  free(this);
}

// Event
int wndHandleMessage(void) {
  if(PeekMessage(&this->_eventMsg, NULL, 0, 0, PM_REMOVE))
    {
      if(this->_eventMsg.message == WM_QUIT)
	{
	  return 0;
	}
      else
	{
	  TranslateMessage(&this->_eventMsg);
	  DispatchMessage(&this->_eventMsg);
	  return 1;
	}
    }
  return 1;
}

//
int wndCreateInstance(const char *title) {
  if(!RegisterClass(&this->_wc)) {
    MessageBox(NULL, "Failed to register window class", "Error",
	       MB_OK | MB_ICONEXCLAMATION);
    return -1;
  }

  if(this->_isFullscreen)
    {
      if(ChangeDisplaySettings(&this->_dmScreenSettings, CDS_FULLSCREEN)
	 != DISP_CHANGE_SUCCESSFUL)
	{
	  MessageBox(NULL, "Fullscreen not supported by your\n video card.", "Error",
		     MB_OK | MB_ICONSTOP);
	      return -1;
	}

      ShowCursor(FALSE);
    }

  AdjustWindowRectEx(&this->_rect, this->_dwStyle, FALSE, this->_dwExStyle);

  if(!(this->_hWnd = CreateWindowEx(this->_dwExStyle,
				    "W32Window",
				    title,
				    WS_CLIPSIBLINGS | WS_CLIPCHILDREN | this->_dwStyle,
				    0, 0,
				    this->_rect.right - this->_rect.left,
				    this->_rect.bottom - this->_rect.top,
				    NULL, NULL, this->_hInstance, NULL)))
    {
      MessageBox(NULL, "Window creation error.", "Error",
		 MB_OK | MB_ICONEXCLAMATION);
      return -1;
    }

  if(!(this->_hDC = GetDC(this->_hWnd)))
    {
      MessageBox(NULL, "Can't create a device context.", "Error",
		 MB_OK | MB_ICONEXCLAMATION);
      return -1;
    }

  ShowWindow(this->_hWnd, SW_SHOW);
  SetForegroundWindow(this->_hWnd);
  SetFocus(this->_hWnd);

  return 0;
}

int wndDestroyInstance(void) {
  if(this->_isFullscreen)
    {
      ChangeDisplaySettings(NULL, 0);
      ShowCursor(TRUE);
    }
  if(this->_hDC && !ReleaseDC(this->_hWnd, this->_hDC))
    {
      return -1;
    }
  if(this->_hWnd && !DestroyWindow(this->_hWnd))
    {
      return -1;
    }
  if(!UnregisterClass("W32Window", this->_hInstance))
    {
      return -1;
    }
  return 0;
}

// Set the parameters of a window
void wndSet(int w, int h, int bpp, int fs) {
  //
  this->_rect.left    = (long) 0;
  this->_rect.right   = (long) w;
  this->_rect.top     = (long) 0;
  this->_rect.bottom  = (long) h;

  //
  this->_hInstance    = GetModuleHandle(NULL);

  //
  this->_wc.hInstance     = this->_hInstance;
  this->_wc.lpfnWndProc   = (WNDPROC) wndProc1;
  this->_wc.hIcon         = LoadIcon(NULL, IDI_WINLOGO);
  this->_wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
  this->_wc.hbrBackground = NULL;
  this->_wc.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
  this->_wc.lpszClassName = "W32Window";
  this->_wc.lpszMenuName  = NULL;
  this->_wc.cbClsExtra    = 0;
  this->_wc.cbWndExtra    = 0;

  //
  this->_isFullscreen = fs;
  if(fs == 1)
    {
      this->_dwExStyle  = WS_EX_APPWINDOW;
      this->_dwStyle    = WS_POPUP;

      memset(&this->_dmScreenSettings, 0, sizeof(this->_dmScreenSettings));
      this->_dmScreenSettings.dmSize       = sizeof(this->_dmScreenSettings);
      this->_dmScreenSettings.dmPelsWidth  = w;
      this->_dmScreenSettings.dmPelsHeight = h;
      this->_dmScreenSettings.dmBitsPerPel = bpp;
      this->_dmScreenSettings.dmFields     = DM_BITSPERPEL |
DM_PELSHEIGHT | DM_PELSWIDTH;
    }
  else
    {
      this->_dwExStyle  = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
      this->_dwStyle    = WS_OVERLAPPEDWINDOW;
    }
}

LRESULT CALLBACK wndProc0(struct SW32Window *this,
			  HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
  switch(iMsg)
    {
    case WM_CLOSE:
      PostQuitMessage(0);
      return 0;
    case WM_KEYDOWN:
      this->_keys[wParam] = 1;
      return 0;
    case WM_KEYUP:
      this->_keys[wParam] = 0;
      return 0;
    case WM_SIZE:
      return 0;
    default:
      return DefWindowProc(hWnd, iMsg, wParam, lParam);
    }
  return 0;
}

//
LRESULT CALLBACK wndProc1(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
  return wndProc0(this, hWnd, iMsg, wParam, lParam);
}


// Double buffering
void wndSwapBuffers(void) {
  SwapBuffers(this->_hDC);
}

// GLContext
int wndGLCreate(const char *title) {
  if(wndCreateInstance(title) < 0)
    return -1;
  if(wndGLCreateContext() < 0)
    return -1;
  return 0;
}

int wndGLDestroy(void) {
  if(wndDestroyInstance() < 0)
    return -1;
  if(wndGLDestroyContext() < 0)
    return -1;
  return 0;
}

int wndGLCreateContext(void)
{
  struct SGLContext *rc = (struct SGLContext*) this->_renderContext;
  if(!(rc->_pixelFormat=ChoosePixelFormat(this->_hDC, &pfd)))
    return -1;
  if(!SetPixelFormat(this->_hDC, rc->_pixelFormat, &pfd))
    return -1;
  if(!(rc->_hRC=wglCreateContext(this->_hDC)))
    return -1;
  if(!(wglMakeCurrent(this->_hDC, rc->_hRC)))
    return -1;
  return 0;
}

int wndGLDestroyContext(void)
{
  struct SGLContext *rc = (struct SGLContext*) this->_renderContext;
  if(rc->_hRC)
    {
      if(!wglMakeCurrent(NULL, NULL))
	return -1;
      if(!wglDeleteContext(rc->_hRC))
	return -1;
      rc->_hRC = NULL;
    }
  return 0;
}



More information about the Gambit-list mailing list