Visual C++ 9.0 2008 Express Edition现在除了IDE常有的缓慢臃肿外,可用性还算蛮好的。向离不开windows与IDE的同学推荐一下。
为了在多个开发平台上无障碍编译程序,CMake的学习与部署看来日益紧迫。CMake的学习曲线相比Autotools来说应该平坦很多。但是协调这么多的编译器也不是很容易的事情,不像Autotools只需要考虑GCC。所以也不是什么容易的事情啦。
现在,终于把wxWidgets的minimal的例子转化为Cmake工程,CMakeLists.txt文件如下:
PROJECT( MINIMAL )
SET(wxWidgets_CONFIGURATION mswu)
SET(wxWidgets_USE_LIBS base core)
FIND_PACKAGE(wxWidgets)
IF(wxWidgets_FOUND)
INCLUDE(${wxWidgets_USE_FILE})
ENDIF(wxWidgets_FOUND)
# Add binary called "minimal" that is built from the source file "minimal.cpp".
# The extension is automatically found.
ADD_EXECUTABLE(minimal WIN32 minimal)
# Link the executable to the wxWidgets library.
TARGET_LINK_LIBRARIES(minimal ${wxWidgets_LIBRARIES})
在VC2008Express下需要注意的是“ADD_EXECUTABLE(minimal WIN32 minimal)”中的WIN32关键字,这样工程链接代码时用的是“/SUBSYSTEM:WINDOWS”而不是默认的“/SUBSYSTEM:CONSOLE”。
CMake默认有findwxWidgets.cmake文件,通过“FIND_PACKAGE(wxWidgets)”指令,支持wxWidgets库的使用。通过学习findwxWidgets.cmake这样的.cmake文件是学习CMake的好方法之一哦。
一般而言,开发一个wxWidgets程序,我们并不需要main函数。因为宏IMPLEMENT_APP(MyApp)已经将main函数封装于内。这个宏完成App的实例化,并调用main函数。将宏展开,它就是这么干的:
//IMPLEMENT_APP(MyApp)
wxAppConsole *wxCreateApp()
{
wxAppConsole::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE,
"your program");
return new MyApp;
}
wxAppInitializer
wxTheAppInitializer((wxAppInitializerFunction) wxCreateApp);
extern MyApp& wxGetApp();
MyApp& wxGetApp() { return *wx_static_cast(MyApp*, wxApp::GetInstance()); }
int main(int argc, char ** argv) { ::wxEntry(argc, argv);}
但是,总有需求无法用这个宏满足的时候。我现在的需求是将FlightGear与wxWidgets联合起来。FlightGear是一个非常强大的飞行模拟程序,其内部视景系统使用OpenSceneGraph,而在与窗口的适配上并且其已经可以使用GLUT、SDL与OSGVIEWER作为后端。我只需要实现一系列的函数,如fgOSMainLoop等,就可以增加一种新的窗口。
要实现的函数是
void fgOSInit(int* argc, char** argv);
void fgOSOpenWindow(int w, int h, int bpp, bool alpha, bool stencil,
bool fullscreen);
void fgOSFullScreen();
void fgOSMainLoop();
void fgOSExit(int code);
void fgSetMouseCursor(int cursor);
int fgGetMouseCursor();
void fgWarpMouse(int x, int y);
int fgGetKeyModifiers();
void fgMakeCurrent();
bool fgOSIsMainCamera(const osg::Camera* camera);
bool fgOSIsMainContext(const osg::GraphicsContext* context);
可以发现,主函数不需要wxWidgets来实现,其需要通过实现fgOSInit来初始化App;通过fgOSOpenWindow来创建窗口;通过fgOSMainLoop来执行主循环。由于fgInit与fgMainLoop是分开实现的,IMPLEMENT_APP宏中的wxEntry函数还需要进一步展开。参考wxWidgets的源代码init.cpp,这两个函数可以这样实现:
- void fgOSInit(int* argc, char** argv)
- {
- // library initialization
- int argc_wx = 1;
- if ( !wxEntryStart(argc_wx, argv) )
- {
- #if wxUSE_LOG
- // flush any log messages explaining why we failed
- delete wxLog::SetActiveTarget(NULL);
- #endif
- exit(-1);
- }
-
- try
- {
- // app initialization
- if ( !wxTheApp->CallOnInit() )
- {
- exit(-1);
- }
- }
- catch(...)
- {
- wxTheApp->OnUnhandledException();
- exit(-1);
- }
- }
-
- void fgOSMainLoop()
- {
- // if wxEntryStart succeeded, we must call wxEntryCleanup even if the code
- // below returns or throws
- wxCleanupOnExit cleanupOnExit;
-
- try
- {
-
- // ensure that OnExit() is called if OnInit() had succeeded
- class CallOnExit
- {
- public:
- ~CallOnExit() { wxTheApp->OnExit(); }
- } callOnExit;
-
- // app execution
- wxTheApp->OnRun();
- }
- catch(...)
- {
- wxTheApp->OnUnhandledException();
- }
- }
void fgOSInit(int* argc, char** argv)
{
// library initialization
int argc_wx = 1;
if ( !wxEntryStart(argc_wx, argv) )
{
#if wxUSE_LOG
// flush any log messages explaining why we failed
delete wxLog::SetActiveTarget(NULL);
#endif
exit(-1);
}
try
{
// app initialization
if ( !wxTheApp->CallOnInit() )
{
exit(-1);
}
}
catch(...)
{
wxTheApp->OnUnhandledException();
exit(-1);
}
}
void fgOSMainLoop()
{
// if wxEntryStart succeeded, we must call wxEntryCleanup even if the code
// below returns or throws
wxCleanupOnExit cleanupOnExit;
try
{
// ensure that OnExit() is called if OnInit() had succeeded
class CallOnExit
{
public:
~CallOnExit() { wxTheApp->OnExit(); }
} callOnExit;
// app execution
wxTheApp->OnRun();
}
catch(...)
{
wxTheApp->OnUnhandledException();
}
}
P.S.
由于WP的编辑器与CoolCode的解释器固执的对’>’与’&’采取不同的态度,代码的显示很糟糕,大家凑合的看算了。