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
分类: 软件开发 | Tags: 跨平台 ARM C | 添加评论(0)
相关文章:
Google Code上两个LPC21XX开源项目 (2009-7-4 14:30:32)
基于ARM的网络收音机 (2009-3-24 19:9:11)
显式指针转换的教训 (2009-2-11 18:27:21)
使用结构体中成员变量指针的教训 (2008-9-19 18:30:42)
结构体中位段、字节对齐并用的教训 (2008-8-31 18:32:53)
浙公网安备 33010602011771号