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@4'
C:\DOCUME~1\malune\LOCALS~1\Temp/ccMXbaaa.o:_W32Window.c:(.text+0x746):
undefined reference to `ChoosePixelFormat@8'
C:\DOCUME~1\malune\LOCALS~1\Temp/ccMXbaaa.o:_W32Window.c:(.text+0x775):
undefined reference to `SetPixelFormat@12'
C:\DOCUME~1\malune\LOCALS~1\Temp/ccMXbaaa.o:_W32Window.c:(.text+0x794):
undefined reference to `wglCreateContext@4'
C:\DOCUME~1\malune\LOCALS~1\Temp/ccMXbaaa.o:_W32Window.c:(.text+0x7bd):
undefined reference to `wglMakeCurrent@8'
C:\DOCUME~1\malune\LOCALS~1\Temp/ccMXbaaa.o:_W32Window.c:(.text+0x7f4):
undefined reference to `wglMakeCurrent@8'
C:\DOCUME~1\malune\LOCALS~1\Temp/ccMXbaaa.o:_W32Window.c:(.text+0x80b):
undefined reference to `wglDeleteContext@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;
}