C语言的跨编译器编译

我有个项目,整个系统有若干软件组成,一个是嵌入式设备,在ARM Developer Suite(ADS)下用C语言开发,另外在PC(x86)平台上还有几个软件,在Visual C++下用C++开发,这几个软件需要相互通讯。对通讯数据的打包、解包是它们之间公用的代码。

尽管我也知道c++可以直接调用c语言,当时,为了图省事儿,我做了一个明知十分愚蠢却故意为之的决定,用版本管理的话来说,我在一个基础版本的基础上,分别定制了几个分支版本,这几个版本算法都是一致的,只是有关编译器语法的部分各自有些细微的差别。

就这样,我跳进了我自己挖的火坑里。每一次增加、修改算法,我都需要在另外的一个版本里,做差不多同样的工作。

就在几天前,忍无可忍的我,决定抽出专门的时间,对这部分代码大动干戈。

首先是语法部分。两个编译器有关字节对齐的指令是不同的,在VC下使用#pragma pack,在ADS下使用__packed关键字。

在VC下,是这样:

//时间变量
#pragma pack(push)
#pragma pack(1)
struct _tag_Time//时间
{
uint8 cSecond;
uint8 cMinute;
uint8 cHour;//24小时值
uint8 cDay;
uint8 cMonth;
uint8 cYear;
};
#pragma pack(pop)

在ADS下,是这样:

__packed struct _tag_Time//时间
{
uint8 cSecond;
uint8 cMinute;
uint8 cHour;//24小时值
uint8 cDay;
uint8 cMonth;
uint8 cYear;
};

为了区分编译环境是VC,还是ADS,我采用了VC编译器自定义的宏_MSC_VER。似乎#pragma pack不能放在#define宏中展开,只好折衷采用下面的办法。

#ifndef _MSC_VER
#define COMPLIER_ADS
#else
#define COMPLIER_VC
#endif
#ifdef COMPLIER_ADS
#definePACK_STRUCT_FIELD(x)__packed x
#definePACK_STRUCT_STRUCT
#definePACK_STRUCT_BEGIN__packed
#definePACK_STRUCT_END
#endif
#ifdef COMPLIER_VC
#definePACK_STRUCT_FIELD(x)
#definePACK_STRUCT_STRUCT
#definePACK_STRUCT_BEGIN
#definePACK_STRUCT_END
#endif
#ifdef COMPILER_VC
#pragma pack(push)
#pragma pack(1)
#endif
PACK_STRUCT_BEGIN
struct _tag_Time//时间
{
uint8 cSecond;
uint8 cMinute;
uint8 cHour;//24小时值
uint8 cDay;
uint8 cMonth;
uint8 cYear;
} PACK_STRUCT_STRUCT;
PACK_STRUCT_END
typedef struct _tag_Time TTime;
#ifdef COMPILER_VC
#pragma pack(pop)
#endif

修改这些跟编译器语法有关的内容后,代码在ADS和VC下都可以正常编译了。

接下来,在PC平台下,我有多个软件需要使用此代码,所以,将这部分代码抽取出来放在一个单独的工程里,供其它工程公用,做成静态链接库是比较合适的方法。

在这个过程中,碰到些小挫折,囫囵吞枣似的通过google解决掉,但是依然没弄懂其中的原理,留记之,怕日后又忘掉了。

碰到的两个错误是:

1、LNK2019: 无法解析的外部符号... ...

解决方法:

在声明函数的.h头文件中,使用extern "C"修饰函数。

#ifdef __cplusplus
extern "C" {
#endif
//函数声明
//....
#ifdef __cplusplus
}
#endif

另外,还要确认静态链接库工程的调用约定为__cdecl(默认)。设置方法:配置属性 -> C/C++ -> 高级 -> 调用约定。可能使用__stdcall可以供Delphi语言调用,但是我没有尝试成功。

2、LNK2005: "private: __thiscall type_info::type_info(class type_info const &)" (??0type_info@@AAE@ABV0@@Z) 已经在 libcmt.lib(typinfo.obj)

解决方法:

修改静态链接库工程的“运行时库”设置,与主工程保持一致。缺省值为“多线程DLL”或者“多线程调试DLL”,修改为“多线程”或者“多线程调试”。

设置方法:配置属性 -> C/C++ -> 代码生成 -> 运行时库。



在csdn论坛上,有高人指点我,可以使用制作针对不同平台的makefile,可能这是终极解决方案,但是我对makefile知之甚少,没有尝试。

Copyright © 2008

继续阅读《C语言的跨编译器编译》的全文内容...

分类: 软件开发 | Tags: 跨平台  ARM  C   | 添加评论(0)

相关文章:

posted on 2008-08-26 18:38  xlander  阅读(517)  评论(0)    收藏  举报

导航