Cocoa OpenGL window in pure C?
I want to open an OpenGL window ( to display and grab keystrokes / mouse events ) in MacOSX.
I don't want to use Glut (since it demandds it be th开发者_开发百科e root thread).
I don't want to learn Objective C.
Is there anyway to access the OpenGL api in pure C?
Thanks!
If you want to grab events on OS X, there are a couple options:
- SDL. Highly recommended, C, not very flexible. You will need to either install it on systems where you use it, or include the framework in your app bundle.
- Cocoa. Use this if you need more flexibility.
- Carbon. I don't recommend using this API, but it is pure C.
Objective C is a very small set of additions to pure C code. You don't have to learn much of it to get by using the Cocoa API. It's not at all the beast that is C++. If you know C, you can learn all you need in a couple hours. All of the best sample code and documentation on the web is for Cocoa, not Carbon. There's OpenGL sample code galore that uses Cocoa, all over the web and on Apple's dev website.
However, all the event handling has to go in the main thread regardless of the API you use. That's the purpose of the main thread, no? You can do OpenGL calls in any thread you like, of course.
I ended up using GLFW.
At first, keyboard events do not work; but they have a sample script for building a bundle. After that, flawless.
SDL?
http://www.libsdl.org/
Simple DirectMedia Layer is a cross-platform multimedia library designed to provide low level access to audio, keyboard, mouse, joystick, 3D hardware via OpenGL, and 2D video framebuffer. It is used by MPEG playback software, emulators, and many popular games, including the award winning Linux port of "Civilization: Call To Power."
SDL supports Linux, Windows, Windows CE, BeOS, MacOS, Mac OS X, FreeBSD, NetBSD, OpenBSD, BSD/OS, Solaris, IRIX, and QNX. The code contains support for AmigaOS, Dreamcast, Atari, AIX, OSF/Tru64, RISC OS, SymbianOS, and OS/2, but these are not officially supported.
Even though you dislike GLUT. How does this sound?
You could have a look at grabbing the GLUT sources from here and modify its main loop. You can find it in the GLUTApplication.m
file. This is how it looks. Think you should easily extract the necessary GLUT calls to place them in your own main loop.
- (void)run
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSRunLoop *runLoop = [[NSRunLoop currentRunLoop] retain];
[self finishLaunching];
__glutEnableVisibilityUpdates();
_running = 1;
while([self isRunning]) {
__glutProcessWorkEvents();
/* Process all pending user events and fire all timers which have
a fire date before or equal to the current system time. */
if(__glutIdleFunc || __glutHasWorkEvents()) {
/* IMPORTANT: This case may _never_ block. */
[self _runMainLoopUntilDate: _distantPast autoreleasePool: &pool];
if(__glutIdleFunc) {
__glutIdleFuncCalled = YES;
__glutIdleFunc();
}
} else {
/* IMPORTANT: We may either block until the next timer in line is
due, or until a new user event arives from the
WindowServer. */
NSDate *limitDate = [runLoop limitDateForMode: NSDefaultRunLoopMode];
[self _runMainLoopUntilDate: limitDate autoreleasePool: &pool];
}
[pool drain];
pool = [[NSAutoreleasePool alloc] init];
}
[runLoop release];
[pool drain];
}
Here's a repo doing exactly what you've asked for.
https://github.com/jimon/osx_app_in_plain_c
To grossly oversimplify what is going on here, you can think of Objective-C as a series of Preprocessor Macros that translate into plain C. See the answer here.
Finding the base C versions of simple Objective-C syntax is the method in play. Where...
[NSApplication sharedApplication];
becomes...
id nsapp = objc_getClass("NSApplication");
id sel_sharedApp = sel_registerName("sharedApplication");
id ret = objc_msgSend(nsapp, sel_sharedApp);
Googling the Apple documentation for functions such as objc_msgSend()
is the path to learn more. This is a very deep rabbit hole.
The only pure C native API on Mac OS X is Carbon. The majority of it is however deprecated and you cannot write 64 bit apps using the Carbon API.
The other API is cocoa - which is objective-C based. The Cocoa framework itself restricts applications to having a single main thread with the message event dispatching on that thread.
glut is implemented on top of Cocoa, and so, on the Mac, inherits that restriction- and so does any other framework you might choose to wrap on top of that: Qt, SDL, glut, etc.
Even if the main thread restriction stands you still need to choose a framework that will save you the hassle of learning objective-c.
glut - if all you are doing is creating a window, and processing input, is a simple choice. SDL and Qt also provide c++ based message processing on MacOSX along with solid support direct access to OpenGL apis for rendering.
I don't want to learn Objective C.
Then forget about writing code to run on OS X.
精彩评论