digitalmars.D - SDLmain and portability
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (25/82) Oct 24 2004 Using SDL on platforms other than Linux and Windows
- Mike Parker (8/10) Oct 24 2004 I disagree with this. There are several applications around the web that...
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (10/14) Oct 24 2004 Unless you want the application to work on Mac OS X (maybe others?)
- Ilya Minkov (23/40) Oct 24 2004 Yup, one very questionable practice. Another questionable practice is=20
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (11/23) Oct 24 2004 The third thing I find questionable is using C macros
Using SDL on platforms other than Linux and Windows has a problem in how it uses a new "main" function... The usual SDL relies on the C preprocessor to redefine "main" as "SDL_main", and they supply a main of their own in the SDLmain library for the applications to use. (this is a gross hack, and requires main() to be written as "int main(int argc, char *argv[])" always or it breaks) The current Windows implementation of SDL-in-D tries to duplicate the behaviour of this code, but in D instead. For Mac OS X for instance, this code is in Objective-C so duplicating it in D is not easy! And it still needs to be called *before* the usual startup code, but after D's main. (that starts up the garbage collector and such D things) In GLUT, which uses less hacks to do things, you simply do:glutInit(&argc, &argv);With SDL, one has to patch the SDLmain library to call it something other than main (and the Windows variants):version (Windows) { // in modified SDLmain library: extern (C) int D_console_main (int argc, char **argv); } version (darwin) { // in modified SDLmain library: extern (C) int D_main (int argc, char **argv); }And then add a utility wrapper to call this new SDL main:import std.string; int SDL_InitApplication(char[][] args) { char*[] c_args = new char*[args.length]; foreach (int i, char[] arg; args) { c_args[i] = toStringz(arg); } int argc = c_args.length; char **argv = cast(char**) c_args; version (Windows) return D_console_main(argc, argv); else version (darwin) return D_main(argc, argv); else return SDL_main(argc, argv); }Finally, the main program is declared something like:import sdl.main; extern(C) int SDL_main(int argc, char **argv) { try { /* Load SDL dynamic link library */ if (SDL_Init(SDL_INIT_NOPARACHUTE) < 0) throw new Error("Error loading SDL"); version(Windows) SDL_SetModuleHandle(GetModuleHandle(null)); // do stuff } finally { SDL_Quit(); } } int main(char[][] args) { return SDL_InitApplication(args); }Skipping the SDL_main part makes the application unportable... SDL_Init and SDL_Quit can be put in the sdl.sdl module in D, but that just makes SDL different from the C version I think ? (and since most example code is in C, it's nice if it's similar) Other D implementations stuck it in: static this() and ~this() --anders PS. This works in Mac OS X, just need to test with Windows/Linux.
Oct 24 2004
Anders F Björklund wrote:Skipping the SDL_main part makes the application unportable...I disagree with this. There are several applications around the web that skip SDL_main entirely. This is often the case when SDL is buried inside a custom framework. The only portability issue is WinMain vs. main on Windows. SDL_main is just a convenience, and without it you really only lose redirection of stdout and stderr. In other words, there's no need for SDL_main functionality in a D binding at all.
Oct 24 2004
Mike Parker wrote:Unless you want the application to work on Mac OS X (maybe others?) On Linux, SDL_main isn't needed at all (usually not even used)... On Windows, it mostly calls SDL_SetModuleHandle(GetModuleHandle(NULL)); and loads the SDL.DLL with SDL_Init(SDL_INIT_NOPARACHUTE) and sets up SDL_Quit to run on exit. All these can be work-aliked in D as well... On Mac OS X, the SDLMain functions sets up a bunch of required Cocoa and Objective-C structures, without which the program will just crash! Besides just redirecting stdout/stderr, that is. (like you mentioned) --andersSkipping the SDL_main part makes the application unportable...In other words, there's no need for SDL_main functionality in a D binding at all.
Oct 24 2004
Anders F Bj=F6rklund schrieb:Using SDL on platforms other than Linux and Windows has a problem in how it uses a new "main" function...True.The usual SDL relies on the C preprocessor to redefine "main" as "SDL_main", and they supply a main of their own in the SDLmain library for the applications to use. (this is a gross hack, and requires main() to be written as "int main(int argc, char *argv[])" always or it breaks)Yup, one very questionable practice. Another questionable practice is=20 using bitfields for flags, but it's another question and it can be=20 tanslated well.The current Windows implementation of SDL-in-D tries to duplicate the behaviour of this code, but in D instead. For Mac OS X for instance, this code is in Objective-C so duplicating it in D is not easy! And it still needs to be called *before* the usual startup code, but after D's main. (that starts up the garbage collector and such D things)What would be the problem of first writing the code you need in=20 Objective C, callable by C, and call it from D? We could also ask the=20 SDL people whether they would want to include such code into the DLL/SO=20 to make porting to other languages easier. Another way was shown by Owen "resistor", who says: "Luckily the ObjC=20 runtime is done in pure C, so it [bridging from D to Objective-C] is at=20 least theoretically doable." Short afterwards, he writes: "I've=20 succeeded in bridging some of the most critical Objective-C internals (classes and objects), and am proud to say that I am now able to=20 introspect the ObjC runtime from D. I ported O'Reilly 'Inside the ObjC Runtime' introspector to D, and it works beautifully!" The code is=20 in the thread called "Docoa, Take 2" on D.gnu newsgroup.SDL_Init and SDL_Quit can be put in the sdl.sdl module in D, but that just makes SDL different from the C version I think ? (and since most example code is in C, it's nice if it's similar) Other D implementations stuck it in: static this() and ~this()Perhaps i'm dumb but i don't see why it wouldn't work in this() and ~this= ()? Otherwise, i don't think that a difference at initailization would be a=20 problem. It is another language library port, so it may be expected to=20 have some (documented) differencies. -eye
Oct 24 2004
Ilya Minkov wrote:Yup, one very questionable practice. Another questionable practice is using bitfields for flags, but it's another question and it can be tanslated well.The third thing I find questionable is using C macros for main function entries, in the header file itself. (such as LoadBMP or BlitSurface, for instance)What would be the problem of first writing the code you need in Objective C, callable by C, and call it from D? We could also ask the SDL people whether they would want to include such code into the DLL/SO to make porting to other languages easier.That's what I did. Or actually I just called the old code "D_main", and included that SDLMain.o in a library called libSDLmain_d.a...Perhaps i'm dumb but i don't see why it wouldn't work in this() and ~this()?It worked just fine, at least once the Windows code was versioned :-)Otherwise, i don't think that a difference at initailization would be a problem. It is another language library port, so it may be expected to have some (documented) differencies.But main problem is that the C library "D_main" must be called before the static constructor is invoked, or SDL won't be setup correctly... Moving that "magic" out of the library made it easier to troubleshoot? --anders
Oct 24 2004