搜索
bottom↓
回复: 38

把C51代码编译成LIB库文件,头文件的宏定义不起作用了。

[复制链接]

出0入27汤圆

发表于 2022-3-10 15:02:35 | 显示全部楼层 |阅读模式
本帖最后由 neutronlmk 于 2022-3-10 15:34 编辑

把C51代码编译成LIB库文件:
c51.h
c51.c
编译成c51.lib给项目调用。
其中c51.h有宏定义给c51.c使用,现在发现调用c51.lib之后,修改c51.h中的宏定义没有效果了。
请问生成c51.lib之后是不是宏定义无法再展开?

补充一下:
这问题的描述应该是“库中如何使用库外的宏定义?”

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2022-3-10 16:22:38 | 显示全部楼层
你这个问题真是愧对你这vip++的身份。编译的原理都没明白。

出1315入193汤圆

发表于 2022-3-10 16:31:24 | 显示全部楼层
宏定义  编译器进行预编译过程  这个有关系么

出1315入193汤圆

发表于 2022-3-10 16:32:32 | 显示全部楼层
shiva_shiva 发表于 2022-3-10 16:22
你这个问题真是愧对你这vip++的身份。编译的原理都没明白。
(引用自2楼)

v++非论坛授予  
欢迎您假如

出0入8汤圆

发表于 2022-3-10 16:44:57 | 显示全部楼层
c51.h 中的宏定义,在编译出 c51.lib 时,已经被展开了,你后面再调整的话,需要重新在编译释放一次 c51.lib。

出0入8汤圆

发表于 2022-3-10 16:45:53 | 显示全部楼层
shiva_shiva 发表于 2022-3-10 16:22
你这个问题真是愧对你这vip++的身份。编译的原理都没明白。
(引用自2楼)

现在的 VIP++ 都是花钱买的,跟技能无关。

出0入0汤圆

发表于 2022-3-10 16:47:28 | 显示全部楼层
了解下编译连接过程,宏定义在编译时就替换和展开了,就是写死到库文件里了。头文件只是告诉使用者一些信息,比如函数原型等,再怎么改,也不会影响到库文件了。库文件虽然在使用者的项目里,但只参与连接过程。

出0入27汤圆

 楼主| 发表于 2022-3-10 16:51:29 | 显示全部楼层
shiva_shiva 发表于 2022-3-10 16:22
你这个问题真是愧对你这vip++的身份。编译的原理都没明白。
(引用自2楼)

身份是买的。
现在我晓得不能用了,有无方法、手段可以达到同样效果?

出0入27汤圆

 楼主| 发表于 2022-3-10 16:54:09 | 显示全部楼层
vuo50z 发表于 2022-3-10 16:47
了解下编译连接过程,宏定义在编译时就替换和展开了,就是写死到库文件里了。头文件只是告诉使用者一些信息 ...
(引用自7楼)

我学到了,有无方法可以达到我要的效果?
比如一个红外解码程序,我定义#define IR_IO P0_0,我希望用户使用lib可库,并在头文件里面可以改成任意IO。

出0入188汤圆

发表于 2022-3-10 16:56:11 | 显示全部楼层
如果宏只是控制流程或者选项,那就用#ifdef,在C里写好各种情况的分支,如果宏作为参数,那最好还是以形参的方式传递,例如做接口函数,专门用来传递参数

出0入0汤圆

发表于 2022-3-10 17:06:41 | 显示全部楼层
neutronlmk 发表于 2022-3-10 16:54
我学到了,有无方法可以达到我要的效果?
比如一个红外解码程序,我定义#define IR_IO P0_0,我希望用户 ...
(引用自9楼)

全局变量,宏是编译时的,变量是运行时的。

出0入188汤圆

发表于 2022-3-10 17:11:11 | 显示全部楼层
neutronlmk 发表于 2022-3-10 16:54
我学到了,有无方法可以达到我要的效果?
比如一个红外解码程序,我定义#define IR_IO P0_0,我希望用户 ...
(引用自9楼)

可以用这个路思来试试,IO操作不要写死在库里,库外写一个IO读写函数,具体操作哪个IO,通过形参来给定,通过参数来传递你具体要操作哪个IO

出0入27汤圆

 楼主| 发表于 2022-3-10 17:42:34 | 显示全部楼层
本帖最后由 neutronlmk 于 2022-3-10 17:44 编辑
hjjnt2008 发表于 2022-3-10 16:56
如果宏只是控制流程或者选项,那就用#ifdef,在C里写好各种情况的分支,如果宏作为参数,那最好还是以形参的 ...
(引用自10楼)


用 #ifdef 不行,生成lib也只有生成时选择的唯一项。
IO口也不好作为参数传递
为难在这里

出0入188汤圆

发表于 2022-3-10 17:50:16 | 显示全部楼层
neutronlmk 发表于 2022-3-10 17:42
用 #ifdef 不行,生成lib也只有生成时选择的唯一项。
IO口也不好作为参数传递
为难在这里 ...
(引用自13楼)

动动脑筋,IO做参数传递还是有办法的

出10入95汤圆

发表于 2022-3-10 18:15:03 | 显示全部楼层
用变量传输了

出0入75汤圆

发表于 2022-3-10 18:25:07 | 显示全部楼层
neutronlmk 发表于 2022-3-10 17:42
用 #ifdef 不行,生成lib也只有生成时选择的唯一项。
IO口也不好作为参数传递
为难在这里 ...
(引用自13楼)

IO口控制预留回调函数,让用户自己实现。

出0入27汤圆

 楼主| 发表于 2022-3-10 18:27:04 | 显示全部楼层
Doding 发表于 2022-3-10 18:25
IO口控制预留回调函数,让用户自己实现。
(引用自16楼)

盼能最具体点

出0入75汤圆

发表于 2022-3-10 18:29:17 | 显示全部楼层
neutronlmk 发表于 2022-3-10 18:27
盼能最具体点
(引用自17楼)

需要操作IO时,把原来的IO0 = 1换成函数,把IO0和1作为参数传进去,用户实现这两参数怎么操作IO。

出0入36汤圆

发表于 2022-3-10 21:02:52 | 显示全部楼层
一般是把不怎么变动的代码或算法编译成lib吧?  像楼主举的例子,是否应该把硬件相关剥离出来? 就算是不变动IO生成lib后跨硬件也不通用啊。  如果是我我会这么做把红外解码做成lib,接口为  IR_Decode(IR_GPIO_LEVEL)  然后在.h文件里将IR_GPIO_LEVEL这个宏定义为IO的电平获取代码,#define IR_IO P0_0  就是读P0_0了 结果只能是0或1被传入。想用哪个IO就 #define IR_IO PX_X

出0入18汤圆

发表于 2022-3-10 21:35:19 来自手机 | 显示全部楼层
搞个操作io的回调函数,这样就能交互了

出0入4汤圆

发表于 2022-3-10 22:56:34 | 显示全部楼层
写个函数吧,在lib里调用这个函数就可以了。。。

出0入27汤圆

 楼主| 发表于 2022-3-11 05:48:32 来自手机 | 显示全部楼层
laujc 发表于 2022-3-10 22:56
写个函数吧,在lib里调用这个函数就可以了。。。
(引用自21楼)

看来只有这个办法了

出0入27汤圆

 楼主| 发表于 2022-3-11 09:04:19 来自手机 | 显示全部楼层
laujc 发表于 2022-3-10 22:56
写个函数吧,在lib里调用这个函数就可以了。。。
(引用自21楼)

读写io的操作可以写个函数给lib调用,曹亮有什么好建议?这个常量也偶尔需要修改的。常量的数量还很多,不适合用全局变量把他们传进去。

出0入8汤圆

发表于 2022-3-11 09:19:48 | 显示全部楼层
neutronlmk 发表于 2022-3-11 09:04
读写io的操作可以写个函数给lib调用,曹亮有什么好建议?这个常量也偶尔需要修改的。常量的数量还很多, ...
(引用自23楼)

你没明白本质,

我帮忙说细一点,最直接的面向接口编程:
将 lib 里面涉及到 IO 操作的,抽象封装为一套 IO 操作接口函数就好了,也就是对 IO 的操作,都是通过接口来访问操作。
到时候提供 lib 的同时,需要提供一套默认的 IO 操作接口函数的实现源码(如果改变了 IO 口,相应的调整这份源码的实现就好了)。

出0入27汤圆

 楼主| 发表于 2022-3-11 09:24:51 | 显示全部楼层
security 发表于 2022-3-11 09:19
你没明白本质,

我帮忙说细一点,最直接的面向接口编程:
(引用自24楼)

我有点点理解了。
我决定用一个c封装好读写IO的子程序,通过lib调用子程序要实现我的要求。
目前有另一个难题:众多的常量怎么传递进去?

出0入16汤圆

发表于 2022-3-11 09:31:33 | 显示全部楼层
回调函数,在LIB里面使用函数指针方式调用,LIB外把函数指针赋个具体的函数就行了

出0入8汤圆

发表于 2022-3-11 09:37:29 | 显示全部楼层
neutronlmk 发表于 2022-3-11 09:24
我有点点理解了。
我决定用一个c封装好读写IO的子程序,通过lib调用子程序要实现我的要求。
目前有另一个 ...
(引用自25楼)

需要修改的就不是常量了,不想用全局变量传递的话,照样用接口形式传递。

出0入27汤圆

 楼主| 发表于 2022-3-11 09:50:48 | 显示全部楼层
security 发表于 2022-3-11 09:37
需要修改的就不是常量了,不想用全局变量传递的话,照样用接口形式传递。 ...
(引用自27楼)

使用参数传递,参数就太多。
还是以红外解码为例,定时扫描红外信号引导码9ms,用50us扫描有一组上限下限,用100us扫描又是另一组上限下限。
如果在c文件使用宏定义,即使使用任意xxUS来扫描,编译器自动把上限下限自动运算出来,直接供程序使用。
编译成lib就不方便了。
总不能引导码,bit0,bit1的时序上限下限都做传进去。

出0入16汤圆

发表于 2022-3-11 09:54:42 | 显示全部楼层
neutronlmk 发表于 2022-3-11 09:50
使用参数传递,参数就太多。
还是以红外解码为例,定时扫描红外信号引导码9ms,用50us扫描有一组上限下限 ...
(引用自28楼)

参数整理一下做成结构体,直接结构体指针传进去,没必要使用宏定义

出0入8汤圆

发表于 2022-3-11 10:04:57 | 显示全部楼层
neutronlmk 发表于 2022-3-11 09:50
使用参数传递,参数就太多。
还是以红外解码为例,定时扫描红外信号引导码9ms,用50us扫描有一组上限下限 ...
(引用自28楼)

29 楼童鞋,是一种方法,另一种方法就是提供一个接口函数,例如:
  1. void GetXxxConfigs(uint8_t *xx0, uint8_t *xx1, uint8_t *xx2)
  2. {
  3.         // 引导时间
  4.         *xx0 = ;
  5.         // 上限
  6.         *xx1 = ;
  7.         // 下限
  8.         *xx2 = ;
  9. }
复制代码

出0入27汤圆

 楼主| 发表于 2022-3-11 10:34:14 | 显示全部楼层
本帖最后由 neutronlmk 于 2022-3-11 10:43 编辑
security 发表于 2022-3-11 10:04
29 楼童鞋,是一种方法,另一种方法就是提供一个接口函数,例如:
(引用自30楼)


感谢,用接口函数方法直观些,代码可以实现封装到lib了。
我看看使用这个方法会增加多少rom。
——————
刚刚测试了,一个接口函数返回一个值,程序中直接使用,不增加开销。

出0入27汤圆

 楼主| 发表于 2022-3-11 12:05:24 | 显示全部楼层
security 发表于 2022-3-11 10:04
29 楼童鞋,是一种方法,另一种方法就是提供一个接口函数,例如:
(引用自30楼)

再请教:
宏定义:
#define CRC16_CCITT_POLY                0x1021


单独一个c文件:
uint16_t u16_GetCrc16Poly(uint16_t fu16_Poly)
{
    return fu16_Poly;
}


lib中代码:
u16_CPoly = u16_GetCrc16Poly(CRC16_CCITT_POLY);


测试lib仍然没有把值传递进去,是哪里搞错了?

出0入16汤圆

发表于 2022-3-11 13:07:15 | 显示全部楼层
LIB:
uint16 mfu16_Poly;
void SetCrC16(uint16_t fu16_Poly)
{
mfu16_Poly=poly;
}

uint16 GetCrc16(void)
{
        return mfu16_Poly*....;
}

出0入8汤圆

发表于 2022-3-11 13:37:46 | 显示全部楼层
neutronlmk 发表于 2022-3-11 12:05
再请教:
宏定义:

(引用自32楼)

看 33 楼。

你那个 lib,又直接将接口函数的实参用宏来实现,编译的时候,宏已经被展开为常量了。

出0入0汤圆

发表于 2022-3-11 13:57:35 | 显示全部楼层
neutronlmk 发表于 2022-3-11 12:05
再请教:
宏定义:

(引用自32楼)

要理解编译时和运行时

出0入27汤圆

 楼主| 发表于 2022-3-11 14:15:32 | 显示全部楼层
初音之恋 发表于 2022-3-11 13:07
LIB:
uint16 mfu16_Poly;
void SetCrC16(uint16_t fu16_Poly)
(引用自33楼)

有点理解。这样写法,是不是使用前还得先调用一下接口函数,然后再调用算法的函数才完成一次使用?把程序给人调用还得教一教啊。

按你29楼的思路,是不是可以直接用一个单独的c文件,把这些宏定义的数据搞成一个全局常量数组,然后lib里面直接取数组来用?

出0入16汤圆

发表于 2022-3-11 14:34:19 | 显示全部楼层
neutronlmk 发表于 2022-3-11 14:15
有点理解。这样写法,是不是使用前还得先调用一下接口函数,然后再调用算法的函数才完成一次使用?把程序 ...
(引用自36楼)

嗯比如
外部:
DevInfo mDevInfo;

void DeviceInit(void)
{
        mDevInfo.data1=a;
        mDevInfo.data2=b;
       LIBDeviceInit(&mDevInfo);

       LIB_Runing();
}

LIB:
typedef struct
{
        int dabta1;
        int data2;
}DevInfo,*pDevInfo;

pDevInfo mDevinfo_t;

void LIBDeviceInit(pDevInfo devinfo)
{
       mDevinfo_t=devinfo;
}

void LIB_Runing(void);
......

出0入27汤圆

 楼主| 发表于 2022-3-11 14:38:09 | 显示全部楼层
本帖最后由 neutronlmk 于 2022-3-11 16:28 编辑
初音之恋 发表于 2022-3-11 14:34
嗯比如
外部:
DevInfo mDevInfo;
(引用自37楼)




我用一个独立c,设一全局常量数组来存这些宏定义的数据,只增加一点rom的开销。
等下试一试。


——————

测试OK,就这样来封装我的程序了。

出0入0汤圆

发表于 2022-3-11 16:08:48 | 显示全部楼层
常量只能全局变量了。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-29 12:32

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表