neutronlmk 发表于 2022-3-10 15:02:35

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

本帖最后由 neutronlmk 于 2022-3-10 15:34 编辑

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

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

shiva_shiva 发表于 2022-3-10 16:22:38

你这个问题真是愧对你这vip++的身份。编译的原理都没明白。

lb0857 发表于 2022-3-10 16:31:24

宏定义编译器进行预编译过程这个有关系么

lb0857 发表于 2022-3-10 16:32:32

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

v++非论坛授予{:titter:} {:titter:}
欢迎您假如

security 发表于 2022-3-10 16:44:57

c51.h 中的宏定义,在编译出 c51.lib 时,已经被展开了,你后面再调整的话,需要重新在编译释放一次 c51.lib。

security 发表于 2022-3-10 16:45:53

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

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

vuo50z 发表于 2022-3-10 16:47:28

了解下编译连接过程,宏定义在编译时就替换和展开了,就是写死到库文件里了。头文件只是告诉使用者一些信息,比如函数原型等,再怎么改,也不会影响到库文件了。库文件虽然在使用者的项目里,但只参与连接过程。

neutronlmk 发表于 2022-3-10 16:51:29

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

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

neutronlmk 发表于 2022-3-10 16:54:09

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

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

hjjnt2008 发表于 2022-3-10 16:56:11

如果宏只是控制流程或者选项,那就用#ifdef,在C里写好各种情况的分支,如果宏作为参数,那最好还是以形参的方式传递,例如做接口函数,专门用来传递参数

vuo50z 发表于 2022-3-10 17:06:41

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

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

hjjnt2008 发表于 2022-3-10 17:11:11

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

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

neutronlmk 发表于 2022-3-10 17:42:34

本帖最后由 neutronlmk 于 2022-3-10 17:44 编辑

hjjnt2008 发表于 2022-3-10 16:56
如果宏只是控制流程或者选项,那就用#ifdef,在C里写好各种情况的分支,如果宏作为参数,那最好还是以形参的 ...
(引用自10楼)

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

hjjnt2008 发表于 2022-3-10 17:50:16

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

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

ddcour 发表于 2022-3-10 18:15:03

用变量传输了

Doding 发表于 2022-3-10 18:25:07

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

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

neutronlmk 发表于 2022-3-10 18:27:04

Doding 发表于 2022-3-10 18:25
IO口控制预留回调函数,让用户自己实现。
(引用自16楼)

盼能最具体点

Doding 发表于 2022-3-10 18:29:17

neutronlmk 发表于 2022-3-10 18:27
盼能最具体点
(引用自17楼)

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

GZZXB 发表于 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

tang_qianfeng 发表于 2022-3-10 21:35:19

搞个操作io的回调函数,这样就能交互了

laujc 发表于 2022-3-10 22:56:34

写个函数吧,在lib里调用这个函数就可以了。。。

neutronlmk 发表于 2022-3-11 05:48:32

laujc 发表于 2022-3-10 22:56
写个函数吧,在lib里调用这个函数就可以了。。。
(引用自21楼)

看来只有这个办法了

neutronlmk 发表于 2022-3-11 09:04:19

laujc 发表于 2022-3-10 22:56
写个函数吧,在lib里调用这个函数就可以了。。。
(引用自21楼)

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

security 发表于 2022-3-11 09:19:48

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

你没明白本质,

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

neutronlmk 发表于 2022-3-11 09:24:51

security 发表于 2022-3-11 09:19
你没明白本质,

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

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

初音之恋 发表于 2022-3-11 09:31:33

回调函数,在LIB里面使用函数指针方式调用,LIB外把函数指针赋个具体的函数就行了

security 发表于 2022-3-11 09:37:29

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

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

neutronlmk 发表于 2022-3-11 09:50:48

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

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

初音之恋 发表于 2022-3-11 09:54:42

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

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

security 发表于 2022-3-11 10:04:57

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

29 楼童鞋,是一种方法,另一种方法就是提供一个接口函数,例如:void GetXxxConfigs(uint8_t *xx0, uint8_t *xx1, uint8_t *xx2)
{
        // 引导时间
        *xx0 = ;
        // 上限
        *xx1 = ;
        // 下限
        *xx2 = ;
}

neutronlmk 发表于 2022-3-11 10:34:14

本帖最后由 neutronlmk 于 2022-3-11 10:43 编辑

security 发表于 2022-3-11 10:04
29 楼童鞋,是一种方法,另一种方法就是提供一个接口函数,例如:
(引用自30楼)

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

neutronlmk 发表于 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仍然没有把值传递进去,是哪里搞错了?

初音之恋 发表于 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*....;
}

security 发表于 2022-3-11 13:37:46

neutronlmk 发表于 2022-3-11 12:05
再请教:
宏定义:

(引用自32楼)

看 33 楼。

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

vuo50z 发表于 2022-3-11 13:57:35

neutronlmk 发表于 2022-3-11 12:05
再请教:
宏定义:

(引用自32楼)

要理解编译时和运行时

neutronlmk 发表于 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里面直接取数组来用?

初音之恋 发表于 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);
......

neutronlmk 发表于 2022-3-11 14:38:09

本帖最后由 neutronlmk 于 2022-3-11 16:28 编辑

初音之恋 发表于 2022-3-11 14:34
嗯比如
外部:
DevInfo mDevInfo;
(引用自37楼)

{:handshake:} {:handshake:} {:handshake:}

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


——————

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

huangqi412 发表于 2022-3-11 16:08:48

常量只能全局变量了。
页: [1]
查看完整版本: 把C51代码编译成LIB库文件,头文件的宏定义不起作用了。