2009年5月17日

在windows下编译vcf2csv

  今天(5月17日)vcf2csv出了新版v0.0.5。这对我来说很有纪念意义(虽然好多人不一定知道我在说什么),因为这个版本是我和作者反馈一个问题之后,作者很热情地帮我解决了问题,然后放出的新版本。故事的经过大概是这样的:

起因


  最近要把一个vcf文件中的电话号码导出来,就到网上搜索vcf的转换软件,一搜一大把,最后筛选出下面三个(都是免费的):
vcf2csv C语言编写
vcard2xls 基于Excel的宏编写
在线服务 : http://labs.brotherli.ch/vcfconvert/
  当时因为机子上没有ms office,又正在学C语言,而且不太敢把那么多电话号码用在线服务转换,于是就选择了vcf2csv。

  但是下载下来才发现,里面竟然只有linux的版本(当时还是v0.0.4版)。幸好vcf2csv是开源软件,源代码已经在压缩包里面了,而且作者提到使用ansi c编写的,源代码的主要部分只有一个c和一个h文件,干脆直接编译一个出来,应该问题不大。

  于是先做好准备工作:

  vcf2cvs的src目录下的makefile中的cc改成gcc
rm -f ……改为

rm -i -f *.o *.d vcf2csv
  cmd或者sh下转到vcf2csv,

make all

  结果果然出错了:

undefined reference to `index'

index函数和strchr函数的问题


  查看了一下源代码,原来是没有定义index函数就直接调用了

  搜搜得到:在Google code搜索,发现index函数有几种不同的实现方法(分别在libc、gcc、gdb的源码中),都大同小异,而我搜遍mingw的头文件也没找到index函数的定义。后来一查才发现,index函数的定义原来在string.h中!!!我倒!我搜索了C Standard Library,里面也没有index函数的说明, 那么,究竟index函数是在哪里定义的呢?
但令我困惑的是,有的书上说应该在,但是我的string.h(MinGW自带的中却没有!)网上搜索一下,有的有,有的没有……


  于是试着修改vcf2csv.c的源代码,添加一个index函数的实现,居然make成功了。不过使用的时候却出错了:

vcf2csv -i test.vcf
ERROR vcard error? malicous line in vcard?
  不会吧,好不容易编译成功了,居然vCard有问题?可是我又在我的linux系统下运行了软件包中的linux版本,却没有问题!这说明不是我的vCard文件的问题。

  后来在google code的中搜索到的man.c - man/src中发现一句:
/* if we don't have the strchr() and strrchr() functions,
* then we must fall back to index() and rindex() respectively,
* but (apparently) these aren't always prototyped in string.h
*/
#ifndef index
/* i.e. NOT using strchr()
*/
extern char *index (const char *, int);
#endif
#ifndef rindex
/* i.e. NOT using strrchr()
*/
extern char *rindex (const char *, int);
#endif
  原来index不总是存在于string.h中的,后来才知道被strchr函数替代了

  以下两篇文章讲述了index函数和strchr函数的渊源:
MirOS Manual: index(3), strchr(3)
https://www.mirbsd.org/htman/i386/man3/index.htm
PATCH Replace index() with strchr() in read-rtl.c:
http://gcc.gnu.org/ml/gcc-patches/2004-09/msg01193.html

  引用一下:
Not all platforms (such as MinGW) have index() used in read-rtl.c,
causing a bootstrap failure on these targets. index() is not in
Standard C, and POSIX recommends that strchr() (which is in Standard C)
be used instead.
大意是说,index不是标准的c库函数,Mingw这样的平台就没有这个index函数(怪不得搜索不到)
POSIX推荐使用strchr来替代index。

The index() function is an old synonym for strchr().
前者是后者的较旧的同义词

The strchr() function conforms to ANSI X3.159-1989 ("ANSI C").
strchr函数遵循ANSI C标准

The index() function is deprecated and shouldn't be used in new code.
index函数已经被废弃,不应该在新的代码中使用
  终于明白了!

  这里有一个strchr的例子:http://www.cplusplus.com/reference/clibrary/cstring/strchr/

  罕见的讨论index函数的帖子,中文网站上极少的关于index的资料,不过ms用处不大:
http://bbs.chinaunix.net/viewthread.php?tid=1069545
http://bbs.chinaunix.net/viewthread.php?tid=1390765

Linux和windows的差别


  但是,把vcf2csv代码中的index函数替换为strchr函数之后,make all成功,编译通过,exe文件也正常生成,但是运行时还是出错:
vcf2csv -i test.vcf
ERROR vcard error? malicous line in vcard?
  非常奇怪,在linux下工作正常,在win下就出错,天啊,到底哪儿出问题了?难道真是linux和windows的问题,不会吧,这个小程序应该不会依赖操作系统特性吧?


关于make clean


  后来,make clean又出错:
H:\vcf2csv>make clean
make -C src clean
make[1]: Entering directory `H:/vcf2csv/src'
rm -f *~ *.o *.d vcf2csv
zsh: no matches found: *~
make[1]: *** [clean] Error 1
make[1]: Leaving directory `H:/vcf2csv/src'
make: *** [clean] Error 2
  zsh: no matches found: *~ 出现这一句的原因应该是unxutils的sh.exe实际上是linux下的zsh移植到win下的

  参考这篇文章:http://zsh.dotsrc.org/Intro/intro_8.html

  大意是说zsh下rm比较安全,rm -f *~ *.o *.d vcf2csv这样的写法是不行的,会返回no matches found错误

  改为rm -i -f *.o *.d vcf2csv后,make clean 成功!

  关于zsh可参考:终极Shell——Zsh http://linuxtoy.org/archives/zsh.html


问题的解决


  后来我通过邮件联系了作者(我还是第一次正式的和外国人书面交流呢),作者是个德国人,非常热情,还谦虚和我说他英语不太好,其实比我强多了:) 作者说很愿意帮助我,会用周末解决这个问题。果然,今天新版本就出来了,不知怎么说才好,只能一个劲的thank you very much,呵呵。


总结


  由于本人的水平有限,上述问题对于会编程的人来说可能不算什么问题,可对于我这个初学者来说,这样的经历可谓获益匪浅。亲历了一下自己动手编译软件的乐趣,知道了index和strchr的故事,结交了一个外国朋友,还顺便提高了英文水平,真的学到了不少东西。谨以此文为纪,自勉。

本文地址:http://ienjoyinfo.blogspot.com/2009/05/windowsvcf2csv.html

0 评论:

发表评论