前面提到由于ACE和QT对main都有预定义,他们都是为了简化对入口函数的定义,以及一些基本的初始化。当2则相遇时,必须对其中一个做适当的调整。这里选择了ACE框架做调整,简单的定义一个ACE_DOESNT_DEFINE_MAIN虽然可以避免冲突,但许多ACE的框架无法正常运行。这里选取examples/c++npv2中的WFMO_Reactor_Logging_Server做测试,采用ACE_DOESNT_DEFINE_MAIN后,无法开启TCP监听。
在OS_main.h中,可以看到根据目标平台,ACE_TMAIN被替换成了相关的初始化函数,比如Win32下,我们写的“主函数”实际上在一个对象的方法中被调用,这个对象的构造和析构分别完成了ACE框架的初试化和结束工作。我们必须去掉关于"main"的预编译指令,修改片段如下:
.......................
# else /* ! (ACE_WIN32 && ACE_USES_WCHAR) */
ACE_BEGIN_VERSIONED_NAMESPACE_DECL
class ACE_Export ACE_Main_Base
{
public:
ACE_Main_Base ();
virtual ~ACE_Main_Base ();
int run (int, char *[]);
virtual int run_i (int, char *[]) = 0;
};
ACE_END_VERSIONED_NAMESPACE_DECL
/*
** LabVIEW RT cannot directly use an executable. Need to build the program
** as a DLL and call it from something else. The ACE test framework knows this
** trick and uses a LabVIEW RT target-resident control program to load a
** DLL, look up it's main() entrypoint, and call it.
*/
# if defined (ACE_BUILD_LABVIEW_EXE_AS_DLL)
extern "C" __declspec (dllexport) int main (int, char *[]);
# endif /* ACE_BUILD_LABVIEW_EXE_AS_DLL) */
/*# define main \ */
/*ace_main_i (int, char *[]); \ */
int ace_main_i (int, char *[]); \
ACE_BEGIN_VERSIONED_NAMESPACE_DECL \
ACE_Export int ace_os_main_i (ACE_Main_Base&, int, char *[]); \
class ACE_Main : public ACE_Main_Base {int run_i (int, char *[]);}; \
inline int ACE_Main::run_i (int argc, char *argv[]) \
{ \
return ace_main_i (argc, argv); \
} \
ACE_END_VERSIONED_NAMESPACE_DECL \
/*int \ */
/*ACE_MAIN (int argc, char *argv[]) /* user's entry point, e.g., wmain */
/*{ \ */
/* ACE_Main m; \ */
/* return m.run (argc, argv); /*ace_os_main_i (m, argc, argv); what the user calls "main" */ \
/*} \ */
/*int \ */
/*ace_main_i */
# endif /* ACE_WIN32 && ACE_USES_WCHAR */
................
这样在main中显式执行下面的代码:
ACE_Main m;
return m.run (argc, argv); /*ace_os_main_i (m, argc, argv); what the user calls "main" */
然后再实现int ace_main_i (int, char *[]);即可 ,如此修改后的WFMO_Reactor_Logging_Server.cpp如下:
............
int ace_main_i (int argc, char *argv[])
{
const size_t N_THREADS = 4;
ACE_WFMO_Reactor wfmo_reactor;
ACE_Reactor reactor (&wfmo_reactor);
Server_Logging_Daemon *server;
// Ignore argv[0]...
--argc; ++argv;
ACE_NEW_RETURN (server,
Server_Logging_Daemon (argc, argv, &reactor),
1);
Quit_Handler quit_handler (&reactor);
ACE_Thread_Manager::instance ()->spawn_n
(N_THREADS, event_loop, &reactor);
return ACE_Thread_Manager::instance ()->wait ();
}
int main(int argc, char *argv[])
{
ACE_Main m;
return m.run (argc, argv); /*ace_os_main_i (m, argc, argv); what the user calls "main" */ \
}
重新编译ACE和WFMO_Reactor_Logging_Server后可以正常开启监听。随后我将Linux平台上基于ACE的TCP通信服务程序使用MinGW4.4重新编译,替换ACE_Reactor实现和修改了一些语法问题(Linux环境GCC版本是4.1的,没4.4版的严格)后编译通过,并且能正常运行。MinGW 真是个好东西!