惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

aimingoo的专栏
aimingoo的专栏
腾讯CDC
Y
Y Combinator Blog
L
LangChain Blog
B
Blog
U
Unit 42
P
Proofpoint News Feed
G
Google Developers Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 【当耐特】
WordPress大学
WordPress大学
月光博客
月光博客
Vercel News
Vercel News
雷峰网
雷峰网
T
The Blog of Author Tim Ferriss
MyScale Blog
MyScale Blog
大猫的无限游戏
大猫的无限游戏
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
酷 壳 – CoolShell
酷 壳 – CoolShell
Blog — PlanetScale
Blog — PlanetScale
博客园 - 司徒正美
云风的 BLOG
云风的 BLOG
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 叶小钗

博客园 - xlander

跟实际生活相关的饭否应用 5个跟实际生活相关的Twitter应用 Google Code上两个LPC21XX开源项目 Router牌音箱 基于ARM的网络收音机 博客程序换成了Z-Blog的 音箱?储钱罐? 显式指针转换的教训 使用结构体中成员变量指针的教训 结构体中位段、字节对齐并用的教训 日本某商场里的智能瀑布 ADS下C语言中局部变量的存储位置分配 救活TrackBack的偏方 近期几个开源的嵌入式产品 几个自制心电图的网络资源 哇哦级的贴片焊接教学视频 自动五线谱识别及音乐合成装置 简易指纹识别授权访问系统 PIC18F2550实现的基于HID的USB示波器
C语言的跨编译器编译
xlander · 2008-08-26 · via 博客园 - xlander

我有个项目,整个系统有若干软件组成,一个是嵌入式设备,在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)

相关文章: