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; }
Afficher les réponses par date
On 17-Apr-08, at 12:47 PM, Edward Tate wrote:
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.
Did you try specifying these options on the gsc command line? For example:
gsc -cc-options "-mno-cygwin" -ld-options "-lmingw32 -lgdi32 - lopengl32 -lglu32" _W32Window.ss
You don't need -lgambc, because that is already in gsi.
Marc