前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >gsoap:stub代码(C++)在mingw下与C++11代码一起编译出错

gsoap:stub代码(C++)在mingw下与C++11代码一起编译出错

作者头像
10km
发布2019-05-25 22:18:38
7140
发布2019-05-25 22:18:38
举报
文章被收录于专栏:10km的专栏10km的专栏10km的专栏

版权声明:本文为博主原创文章,转载请注明源地址。 https://cloud.tencent.com/developer/article/1433642

理论上,gsoap生成的代码是可以在各种编译器下编译的。但现实是我用gsoap生成的c++代码,在windows/mingw就没办法编译,在windows/vs2015下可以正常编译,在linux/gcc也能 正常编译,给人的感觉似乎是没有在mingw下做过基本测试(真的是这样吗???)。

简单的错误

仔细研究了编译错误,其实都很简单,都是没有正确判断win32下的编译器类型。

例如下面这段代码(version 2.8.33的stdsoap2.cpp line 12973, soap_string_in函数)

#ifdef WIN32
          m = 0;
          wctomb_s(&m, buf, sizeof(buf), (wchar_t)(c & 0x7FFFFFFF));
#else
          m = wctomb(buf, (wchar_t)(c & 0x7FFFFFFF));
#endif

显然《wctomb》是标准c函数,而 带_s后缀的《wctomb_s》是msvc扩展的安全增强版本的函数。

只用#ifdef WIN32来判断,在msvc下编译是没问题,但用mingw编译时就报错了,因为mingw并没有实现wctomb_s

还好,gsoap的版本更新很快,当我更新到上个月(2016-08-17)发布的最新版本(2.8.34)时,发现上面这个问题被开发者修改了(version 2.8.33的stdsoap2.cpp line 12925, soap_string_in函数)

#if defined(WIN32) && !defined(CYGWIN) && !defined(__MINGW32__) && !defined(__MINGW64__)
            m = 0;
            wctomb_s(&m, buf, sizeof(buf), (wchar_t)(c & 0x7FFFFFFF));
#else
            m = wctomb(buf, (wchar_t)(c & 0x7FFFFFFF));
#endif

虽然修改的不那么漂亮,但总算是改了。

简单的修改

但当我用新版本重新运行wsdl2h,soapcpp2 生成了c++代码,再次尝试mingw下编译时,又报错了,还是类似的问题。

这次问题出在stdsoap2.h(version 2.8.34 line 1299,2.8.34以前的版本都一样)

#ifdef WIN32 
# ifndef HAVE_ISNAN
#  define HAVE_ISNAN
# endif
# define soap_isnan(n) _isnan(n)
# ifndef HAVE_ISINF
#  define HAVE_ISINF
# endif
# define soap_isinf(n) (!_finite(n))
#endif

于是我也依样画葫芦将这段代码修改如下,则编译通过

#if defined(WIN32) && !defined(__MINGW32__) && !defined(__MINGW64__)
# ifndef HAVE_ISNAN
#  define HAVE_ISNAN
# endif
# define soap_isnan(n) _isnan(n)
# ifndef HAVE_ISINF
#  define HAVE_ISINF
# endif
# define soap_isinf(n) (!_finite(n))
#endif

事情就这样结束了么?

我总觉得gsoap不会对这么明显而且简单的问题在之前的那么多版本都解决不了,对于本文一开始我的推断:gsoap没有在mingw下做过基本测试,我总是有点心虚的。

联想到我的系统代码都用c++11标准写的所以我的项目cmake脚本(CMakeLists.txt)中默认对整个项目都增加了-std=c++11选项。

#判断编译器类型,如果是gcc编译器,则在编译选项中加入c++11支持
if(CMAKE_COMPILER_IS_GNUCXX)
    set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
    message(STATUS "optional:-std=c++11")
endif(CMAKE_COMPILER_IS_GNUCXX)

也就是说stdsoap2.cpp实际是在-std=c++11选项下编译的。

会不会是因为这个-std=c++11选项引起的问题呢?

于是我尝试删除-std=c++11选项,恢复前面的所有修改,再编译,则编译通过。

现在问题搞明白了,上面的实验推翻我前面的一系列结论:

gsoap生成的c++代码在c++98标准下编译应该是没问题的, 但gsoap的开发者并没有用-std=c++11选项在mingw下编译测试过,所以会有前面那些问题。

所以解决在gsoap stub代码和C++11代码一起在mingw下编译的问题有两个方案:

方案1.修改自己CMakeLists.txt,将gsoap生成的C++代码与自己的项目c++11代码区分开,不用-std=c++11选项编译gsoap代码,这样就可以避免修改gsoap代码(stdsoap2.h/stdsoap2.cpp)。

方案2.与方案1相反,就像前面的办法一样修改stdsoap2.h/stdsoap2.cpp以解决编译问题.这样可以不用修改自己的CMakeLists.txt,将gsoap生成的c++代码与自己的C++11代码混在一起编译。

选项哪个方案都可以取决哪个方案成本最低,

但我准备选择项方案1—原因是不到万不得已我不会修改第三方代码,这样会增加未来的维护成本 。

不过以现在gsoap每月发布一个版本的更新速度,下一个版本应该就能完美解决mingw下对-std=c++11选项的支持问题了。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年09月06日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简单的错误
  • 简单的修改
  • 事情就这样结束了么?
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档