mingw/vc2008移植问题记录

本文记录了从VC2008到Linux平台移植过程中遇到的各种问题,包括运行时库的选择、inline函数重定义、libevent依赖、errno处理、APR导入、函数声明不一致、snprintf替换、strtoll与strtoull问题、符号无定义、MySQL UDF、WSAStartup、缺少BSD套接字头文件、pthread-w32静态库问题、VC6构造函数初始化表、模板参数与嵌套问题等,并提供了相应的解决方案。
摘要由CSDN通过智能技术生成

注意:以下解决方法不一定适用,仅个人记录备忘

 

关于VC和gcc的区别,请参考以下链接:

gccとVC(日文)

http://homepage1.nifty.com/herumi/prog/gcc-and-vc.html

 

(20131119)

超初心者のプログラム入門

http://www.eonet.ne.jp/~maeda/index.html

 

 

Problem 1: VC2008 运行时库
属性页->C/C++->代码生成->运行时库(一般是MTd和MT)

 

Problem 2: inline函数重定义问题,可以考虑用#if屏蔽掉
#if defined(_MSC_VER) && (_MSC_VER < 1500) //VC 9
inline int inet_pton(int af, register const char *cp, struct in_addr *addr)

 

Problem 3: libevent.lib 依赖问题。
如果使用VC2008,并且建立起libevent源代码工程。可以考虑使用“链接器->输入->附加依赖项”,这样就不再需要添加libevent.lib

 

Problem 4: errno赋值问题
errno = 0需要改为set_errno(0);
原因是vc2008的编译器在多线程时不允许你直接给errno赋值,貌似是为了线程安全,这时候就得写个宏。

 

 

#if defined(_MT) || defined(_DLL)
# define set_errno(x)    (*_errno()) = (x)
#else
# define set_errno(x)    errno = (x)
#endif

 

 

不知道linux怎么处理线程安全(好像linux根本就不需要这么复杂)。

 

Problem 5:APR导入问题。
如果有一天突然想用APR或APU来编程,你就得遇到这种囧问题——不知道怎么在vc2008里链接。
一种方法是:
宏定义添加
APR_DECLARE_EXPORT(补充:或者APU_DECLARE_EXPORT)
WIN32
确保是动态导出api和动态导入APR DLL

附加依赖项目选择使用动态链接的lib(以防万一把apr和apu的都加上)
libapr-1.lib libaprutil-1.lib
如果不知道apr为何物,就最好别管这种复杂问题(Apache httpd的代码和API需要高手才看得懂的)
推荐用动态库(不会遇到一堆链接错误)如果用静态库要改用另一套lib和APR_DECLARE_STATIC

 

Problem 6: 函数声明和定义不同。
可能vc2008会对类型很敏感。最好改为统一。

 

Problem 7: snprintf问题
Windows SDK没有snprintf这个函数,用_snprintf代替

 

 

#ifndef snprintf
#define snprintf _snprintf
#endif

 

 

Problem 8: strtoll和strtoull问题

 

 

#if _MSC_VER < 1300
#define strtoll(p, e, b) ((*(e) = (char*)(p) + (((b) == 10) ? strspn((p), "0123456789") : 0)), _atoi64(p))
#else
#define strtoll(p, e, b) _strtoi64(p, e, b) 
#endif

#ifndef strtoull
#define strtoull strtoul
#endif

 

 

遇到这种问题需要查SDK的手册,你会发现有个叫_atoi64的API(这个函数很早就有了,用于32位操作系统上,定义在stdlib.h)。
当然如果你不喜欢上面代码写得那么复杂,可以一概改为_atoi64。另外,还需要知道有个关键字__int64,
可以用它表示有符号和无符号的64位整数(很少出现,除非你要用64位来提高性能)
_strtoi64的用法稍微不同。还有个叫_i64toa的API,是_atoi64的逆转换。

 

补充:可能对于64位整数,还要考虑格式化字符串printf的问题,所以问题远没有这么简单。

 

Problem 9:符号无定义。
比如你用了TransmitFile,你就得加mswsock.lib(不过好像加的顺序有讲究的)
如果不知道加什么,就查sdk帮助和搜索,一般微软会很热心地注明这个API需要用那个lib去
链接。把所有lib加上去试也可以(只是这种方法有点菜)

 

Problem 10:MySQL UDF问题
比较通用的方法是写个.def文件
LIBRARY "xxx"
EXPORTS
...
然后在工程中加入这个def
编译好dll后拷贝到
C:\Program Files (x86)\MySQL\MySQL Server 5.1\lib\plugin
或者根据show variables like "plugin_dir";判断插件位置
如果涉及别的dll,需要把依赖dll拷贝到PATH的路径下,例如
C:\Program Files (x86)\MySQL\MySQL Server 5.1\bin
否则mysqld会因为缺乏dll而启动不了UDF而认为UDF不存在。
创建SQL类似于CREATE FUNCTION xxx RETURNS INT SONAME "xxx.dll";
安装成功后select name, dl from mysql.func;查看
要调试UDF可以用fprintf(stderr,...)的方法,然后用mysqld --console来启动mysqld。
另外最好用debug版测试,万一崩溃了,mysqld会把输出一些堆栈信息到控制台上。

 

Problem 11: WSAStartup和memset问题

 

 

#ifdef WIN32
 {
  WSADATA wsaData;
  if(WSAStartup(MAKEWORD(2,0), &wsaData) != 0) {
   fprintf(stderr, "Socket Initialization Error. Program  aborted\n");
   return 0;
  }
 }
#endif

 

 

这是windows的特有问题(写linux网络程序的人大概会很郁闷),
如果有一天发现getaddrinfo返回非零,
检查一下main函数有没有加WSAStartup。(连127.0.0.1都解析不了会很可笑)。
另外memset也是个需要注意的问题,例如初始化struct addrinfo变量hints需要
memset(&hints, 0, sizeof (hints));(有时候你忽略这个问题会出现一些古怪的结果)
然后给某个成员变量赋值。
linux的写法就不会那么复杂,它用C99的写法,在初始化时直接给变量的成员函数赋初始值。
顺便一提VC支持字符串的全0初始,例如char s[10] = {0};比单纯写char s[10];要安全得多。

 

更正:

VC其实可以像gcc那样给结构体对象赋初值,只不过不是写成 type a={.x = 10, };

而是写成type a={a.x = 10,};所以没必要用memset(低版本的VC则有必要?)

 

problem 12:缺少BSD套接字头文件

在linux网络编程中经常会出现

#include <netinet/tcp.h>
#include <arpa/inet.h>

有时还会有

#include <sys/socket.h>

还有其他,如果只是使用BSD套接字,

问题是,mingw没有(VC也是)。

但windows上的确存在BSD套接字API的子集,只不过需要包含的头文件不是上面那些,而是

 

 

#include <winsock2.h>
#include <ws2tcpip.h>

 

 

如果对这个问题感兴趣,可以参考这些资料:

 

* memcached1.2.6-win32移植的源代码

http://code.jellycan.com/memcached/

 

*PostgreSQL的源码(\src\include\port\win32),对win32的移植

http://www.postgresql.org/ftp/source/ 

 

(注:VC6似乎不行,待考)

 

problem 13:缺少sys/poll.h

win32没有现成的机制实现poll(轮询),也就是说:poll()不可移植

http://lists.zerezo.com/mingw-users/msg05987.html

不过事实上有人给出poll()的非正式实现:

 (未经试验,不过好像可以试试看)

* libmemcached

/poll/poll.c

https://launchpad.net/libmemcached/+download

-------------------------

(2010-09-10:补充drizzle,发现它的源代码包中带有poll.c,不知道是否可用)

* drizzle

https://launchpad.net/drizzle

-------------------------

如果你使用cygwin,这个问题可以忽略(因为默认是有poll.h和poll()的实现)

(补充:

poll其实可以在msys的SDK中使用

msysDVLPR-1.0.0-alpha-1.tar.gz

但最终生成的exe导入了MSYS-1.0.DLL,而MSYS-1.0.DLL不可以单独使用(依赖于msys)

如果只用于msys控制台,可以尝试用这个SDK(gcc version 2.95.3-1)

安装教程:

http://www.mingw.org/wiki/HOWTO_Create_an_MSYS_Build_Environment

注意,它需要与msys目录合并,不是放在/mingw目录下

继续补充:

poll其实有win32的port,参考

WSAPoll

http://msdn.microsoft.com/en-us/library/ms741669(VS.85).aspx

不过这个API仅用于Vista以上

 

problem 14: pthread-w32静态库造成程序崩溃的问题。

由于dll.c中dllmain()调用了这两个API(定义在pthread.h)

PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_attach_np(void);
PTW32_DLLPORT int PTW32_CDECL pthread_win32_process_detach_np(void);

如果pthread-w32被静态链接到程序中,需要在main()函数开头调用pthread_win32_process_attach_np初始化,否则程序会崩溃,且很难找到崩溃的原因(即使使用CDT调试)。

(2014/01/23补注:)代码如下:(在main函数最开始的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值