获取c程序中的.h头文件定义的宏信息

一、需求:获取下面头文件中所有的宏信息

#ifndef __USR_H__
#define __USR_H__
#include <stdio.h>

#define VERSION_STRING     "2.05"
#define VERSION_STRING_LEN 32

#define SUCCESS                            0x00
#define ERR_BASE                           0x00
#define aTEST_ERR_BASE0                          0x100

# define ERR_UNKNOWN                       0x123
#define ERR_INVALID1                      (1 + aTEST_ERR_BASE0)
#define ERR_INVALID2                      ERR_BASE + 2
#define ERR_INVALID3                      ERR_BASE + 3
#define ERR_INVALID4                      4 + aTEST_ERR_BASE0
#define ERR_INVALID5                      (ERR_BASE + 5)

#define BACKUP_DIR                 "/home/test"
#define RUN_DIR                     BACKUP_DIR"/.backup"
#define BASE_CONTENT                "msgfrom"BACKUP_DIR

二、运行结果

三、具体程序(使用python)

# @Time    :   2024/4/18 13:52
# @File    :   test.py
# @Author  :   路人甲-甲
# @Version :   1.0
# @Site    :   https://blog.youkuaiyun.com/wankeng
# @Desc    :   读取c语言中的.h头文件里定义的#define宏信息,并将其存入字典all_define_dict中

import os
import re

all_define_dict = {}

# 匹配格式为#define  TEST_VALUE  “ABC”的情况
def define_value_for_char(content):
    global  all_define_dict
    m = re.match(r"([a-zA-Z0-9_]+)", content)
    if m:
        match_str = m.group(0)
        match_str_len = len(match_str)
        content = content[match_str_len:]
        #去掉前面的空格
        content = content.replace(" ", "").replace("\t","").replace("\n","")
        # 匹配格式为#define  TEST_VALUE  “ABC”的情况
        if content.startswith("\"") and content.endswith("\""):
            m = re.search(r"[a-zA-Z0-9_/.]+", content)
            if m:
                return match_str, str(m.group(0))
        elif content.startswith("\"") and not content.endswith("\""):
            # 匹配格式为#define  TEST_VALUE  “ABC"/BASE_TEST_CHAR
            m = re.search(r"[a-zA-Z0-9_/.]+", content)
            if m:
                before_str_len = len(m.group(0))
                before_str = m.group(0)
                var_name = content[before_str_len + 2:].strip()
                if var_name in all_define_dict:
                    var_value = all_define_dict.get(var_name, None)
                    if var_value is not None:
                        return match_str, before_str +  var_value
        elif (not content.startswith("\"")) and content.endswith("\""):
            # 匹配格式为#define  TEST_VALUE  BASE_TEST_CHAR“/test"
            m = re.search(r"[a-zA-Z0-9_/.]+", content)
            if m:
                var_name_str_len = len(m.group(0))
                var_name = m.group(0)
                after_str = content[var_name_str_len + 1: -1].strip()
                if var_name in all_define_dict:
                    var_value = all_define_dict.get(var_name, None)
                    if var_value is not None:
                        return match_str, var_value + after_str
    return None, None


#匹配格式为#define  TEST_VALUE  (1 + TEST_VALUE)的情况
#匹配格式为#define  TEST_VALUE  (TEST_VALUE + 1)的情况
#匹配格式为TEST_VALUE + 1 没有括号的情况
def define_value_for_int_calculate(content):
    global all_define_dict
    m = re.match(r"([a-zA-Z0-9_]+)", content)
    if m:
        match_str = m.group(0)
        match_str_len = len(match_str)
        content = content[match_str_len:]

        m = re.match(r"\s+(\([a-zA-Z0-9_])", content)
        if m:
            sub_match_len = len(m.group(0))
            #去掉括号和换行符
            temp_value = content[sub_match_len - 1: -2]

            sub_m = re.match(r"\w+", temp_value)
            before_var_value = None
            final_int_value = None
            if sub_m:
                # 匹配格式为(TEST_VALUE + 1)的情况
                before_var_name = sub_m.group(0)
                before_var_value = all_define_dict.get(before_var_name, None)
                if before_var_value is None:
                # 匹配格式为(1 + TEST_VALUE)的情况
                    sub_m = re.match(r"(\d)+\s+", temp_value)
                    if sub_m:
                        sub_match_len = len(sub_m.group(0))
                        sub_content = temp_value[sub_match_len:]
                        search_m = re.search(r"(\w+)", sub_content)
                        if search_m:
                            before_var_name = search_m.group(0)
                            before_var_value = all_define_dict.get(before_var_name, None)
                if before_var_value is not None:
                    #计算(TEST_VALUE+1)的值
                    final_int_value = eval(temp_value.replace(before_var_name, str(before_var_value)))
            # print(f'{match_str}={final_int_value}={temp_value}={before_var_value}=end')
            if final_int_value is not None:
                return match_str, final_int_value
        else:
            #匹配格式为TEST_VALUE + 1 没有括号的情况
            before_var_value = None
            final_int_value = None
            m = re.search(r"[a-zA-Z0-9_]+", content)
            if m:
                sub_match_len = len(m.group(0))
                #去掉括号和换行符
                temp_value = content[sub_match_len -2: -1]
                if temp_value.startswith("\"") or temp_value.endswith("\""):
                    return None, None
                before_var_name = m.group(0)
                before_var_value = all_define_dict.get(before_var_name, None)
                if before_var_value is not None:
                    #计算TEST_VALUE + 1的值
                    final_int_value = eval(temp_value.replace(before_var_name, str(before_var_value)))
                # print(f'{match_str}={final_int_value}={temp_value}={before_var_value}=end')
                if final_int_value is not None:
                    return match_str, final_int_value
    return None, None

# 匹配格式为#define  TEST_VALUE  1的情况
# 匹配格式为#define  TEST_VALUE  1 + BEFORE_TEST_VALUE
def define_value_for_int(content):
    global all_define_dict
    m = re.match(r"([a-zA-Z0-9_]+)", content)
    if m:
        match_str = m.group(0)
        match_str_len = len(match_str)
        content = content[match_str_len:]
        m = re.match(r"\s+(\d)", content)
        # print(f'---{match_str}={m}={content}={match_str_len}=end')
        if m:
            sub_match_len = len(m.group(0))
            value_contents = content[sub_match_len - 1: -1]
            has_space_or_char = re.search(r"[a-zA-Z_]+", value_contents)
            if has_space_or_char:
                # 匹配格式为#define  TEST_VALUE  1 + BEFORE_TEST_VALUE
                before_var_name = value_contents[len(value_contents) - len(has_space_or_char.group(0)) - 1:]
                # 去掉有可能的空格
                before_var_name = before_var_name.strip()
                if before_var_name in all_define_dict:
                    before_var_value = all_define_dict.get(before_var_name, None)
                    if before_var_value is not None:
                        # 计算1 + BEFORE_TEST_VALUE的值
                        final_int_value = eval(value_contents.replace(before_var_name, str(before_var_value)))
                        if final_int_value is not None:
                            return match_str, final_int_value
            else:
                # 匹配格式为#define  TEST_VALUE  1 单纯的数字
                final_int_value = int(content[sub_match_len - 1: -1])
                if final_int_value is not None:
                    return match_str, final_int_value
    return None, None

# 匹配格式为#define  TEST_VALUE  0x1的情况
def define_value_for_hex(content):
    m = re.match(r"([a-zA-Z0-9_]+)", content)
    if m:
        match_str = m.group(0)
        match_str_len = len(match_str)
        content = content[match_str_len:]
        m = re.match(r"\s+0x", content)
        if m:
            sub_match_len = len(m.group(0))
            dist_value_to_int = int(content[sub_match_len:sub_match_len + 8], 16)
            if dist_value_to_int is not None and len(match_str) > 0:
                return match_str, dist_value_to_int
    return None, None

def get_define_dict(org_content):
    key = None
    value = None
    m = re.match(r"(#define\s+|# define\s+)", org_content)
    if m:
        x = m.group(0)
        s = len(x)
        line = org_content[s:]
        key, value = define_value_for_hex(line)
        if key is None and value is None:
            # 单纯的数字
            key, value = define_value_for_int(line)
        if key is None and value is None:
            # 带有运算符的数字
            key, value = define_value_for_int_calculate(line)
        if key is None and value is None:
            # 字符串
            key, value = define_value_for_char(line)
    return key, value

def loadFromC(fn):
    global all_define_dict
    with open(fn, "r",encoding='utf-8') as reg_file:
        for line in reg_file.readlines():
            if line is None or len(line) == 0 or line.startswith("\n") or line.startswith("\r\n" or line.startswith("^M")):
                continue
            key,value = get_define_dict(line)
            if key is not None and value is not None:
                all_define_dict[key] = value
        reg_file.close()
    return all_define_dict


fn = "./test.h"
ret_dict = loadFromC(fn)
print(len(ret_dict))
for k, v in ret_dict.items():
    print(k, v)

四、后续

我们可以思考,根据上面的方法,可以获取此.h文件里定义的方法、结构体、枚举类等信息。我们可以将此信息拿到之后测试这些方法。具体实现方式请私信。

现在我在linux服务器中创建了docker容器,在容器里拉取了openharmony4.1源码,按照矿鸿厂家的编译命令,编译出了矿鸿系统,现在系统工程的sample文件夹里有a01_helloworld等示例代码,我想先把a01_helloworld修改成矿鸿设备发现注册的代码尝试编译,并在后续在sample中新建工程,实现其他接口api的功能调用,我该如何修改a01,请仿照文档中clinet端的示例代码进行修改#include"hcp.h" #define HCP_FAIL (-1) #define MAX_DEVICE_ID_LEN 65 #define EOK 0 char g_hcpDeviceId[MAX_DEVICE_ID_LEN]; uint16_t g_hcpPort; int TestDeviceFound(HcpDeviceInfo *info) { // todo 业务处理由应用按需实现 if (memcpy_s(g_hcpDeviceId, sizeof(g_hcpDeviceId), info->deviceId, sizeof(info->deviceId)) != EOK) { return HCP_FAIL; } g_hcpPort = info->addrs[0].addrInfo.ipAddr.port; return 0; } void TestHcpServiceDead(void) { // todo 业务处理由应用按需实现 } int main() { // App注册,获取hcpId const char *appName = "TestApp"; HcpAppCallback callbackSt = {0}; callbackSt.onDeviceFound = TestDeviceFound; callbackSt.onHcpServiceDead = TestHcpServiceDead; int hcpId = HcpAppRegister(appName, &callbackSt); if (hcpId > 0) { // 非0正值为合法值 printf("HcpAppRegister success, hcpId is %d ", hcpId); } else { printf("HcpAppRegister failed!"); return HCP_FAIL; } // 使用单播发现获取目标设备信息 HcpDiscoverInfo info = {0}; info.medium = UDP_UNICAST; // 表示单播发现 char *dstIp= "192.xxx.x.1"; // 单播发现的目的地址 strcpy_s(info.dstIpString, IP_MAX_LEN, dstIp); // 目的地址填到info中 int ret = HcpDeviceDiscovery(hcpId, &info); if (ret == EOK) { // todo 等待发现成功,在TestDeviceFound回调中异步处理和存储发现的目标设备信息 } int transactionId = 0; IpAddr targetAddr = {0}; // 目的地址结构体 if (strcpy_s(targetAddr.ip, IP_MAX_LEN, dstIp)) { return HCP_FAIL; } targetAddr.port = g_hcpPort; // 填入由设备发现回调返回的信息 TargetConnectInfo targetConnectInfo = {0}; targetConnectInfo.deviceIdLength = strlen(g_hcpDeviceId); // 设备唯一标识符长度 targetConnectInfo.deviceId = g_hcpDeviceId; // 目的设备的设备唯一标识,填入由设备发现回调返回的信息 targetConnectInfo.ipAddrCount = 1; // 连接目的地址数量 if (memcpy_s(targetConnectInfo.ipAddrList, MAX_CONNECT_ADDR_CNT*sizeof(IpAddr), &targetAddr, sizeof(IpAddr)) != EOK) { return HCP_FAIL; } HcpConnectionAttr connAttr = {0}; connAttr.qosLevel = 0; // 建立连接的qos等级 connAttr.sessionType = SESSION_TYPE_MSG; // 连接的会话类型,选择消息类型 ConnectionSetupResult connectionSetupResult = {0}; int connectRet = HcpConnectSync(hcpId, &targetConnectInfo, &connAttr, &connectionSetupResult); if (connectRet != EOK) { return HCP_FAIL; } if (connectionSetupResult.status == 0) { // 连接成功 printf("connectionId is %d\n", connectionSetupResult.connectionId); // TODD 根据返回的连接标识符进行具体业务,以下以读取属性集的值为例 uint16_t status = 0; // 应用调用HcpReadRemoteModelAllAttrValueSync的返回状态 HcpReadModelAttrRequest request = {0}; request.attrSetId= 1; // 读取的远端设备模型id为1 request.attrSetInstanceId = 2; // 读取远端设备模型实例id为2 HcpGetRemoteModelAttrResponse response = {0}; // 接收同步模型实例所有属性读取结果 int result = HcpReadRemoteModelAllAttrValueSync(hcpId, connectionSetupResult.connectionId, &request, &status, &response); if (result != EOK) { // 判断接口返回值 return HCP_FAIL; } if (status != EOK) { // 判断服务状态码 return HCP_FAIL; } // TODO 应用按需进行业务处理 if (response.attrResultList != NULL) { // 此指针不为空,必须进行资源释放 free(response.attrResultList); } } return 0; }
最新发布
03-26
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值