4 06 2008

CMake and wxWidgets

matthewgong | wxWidgets | 0 Comments

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的好方法之一哦。

2 28 2008

wxWidgets与main函数

matthewgong | wxWidgets | 0 Comments

一般而言,开发一个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,这两个函数可以这样实现:

  1. void fgOSInit(int* argc, char** argv)
  2. {
  3.     // library initialization
  4.     int argc_wx = 1;
  5.     if ( !wxEntryStart(argc_wx, argv) )
  6.     {
  7. #if wxUSE_LOG
  8.         // flush any log messages explaining why we failed
  9.         delete wxLog::SetActiveTarget(NULL);
  10. #endif
  11.         exit(-1);
  12.     }
  13.  
  14.     try
  15.     {
  16.         // app initialization
  17.         if ( !wxTheApp->CallOnInit() )
  18.         {
  19.           exit(-1);
  20.         }
  21.     }
  22.     catch(...)
  23.     {
  24.       wxTheApp->OnUnhandledException();
  25.       exit(-1);
  26.     }
  27. }
  28.  
  29. void fgOSMainLoop()
  30. {
  31.     // if wxEntryStart succeeded, we must call wxEntryCleanup even if the code
  32.     // below returns or throws
  33.     wxCleanupOnExit cleanupOnExit;
  34.  
  35.     try
  36.     {
  37.  
  38.         // ensure that OnExit() is called if OnInit() had succeeded
  39.         class CallOnExit
  40.         {
  41.         public:
  42.             ~CallOnExit() { wxTheApp->OnExit(); }
  43.         } callOnExit;
  44.  
  45.         // app execution
  46.         wxTheApp->OnRun();
  47.     }
  48.     catch(...)
  49.     {
  50.       wxTheApp->OnUnhandledException();
  51.     }
  52. }


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的解释器固执的对’>’与’&’采取不同的态度,代码的显示很糟糕,大家凑合的看算了。

© 2006 Matt’s Blog for UBUNTU | Wordpress | dKret2 2.2 | XHTML | CSS | Top |