zoukankan      html  css  js  c++  java
  • C语言实现反射

    高级语言的反射机制,简单来说就是可以通过字符串型获取对应的类或者函数。

    1. 基础形式,c语言结构化编程基础实现
      1)声明
        typedef void (*callback)(void);
        
        typedef struct {
            const char *name;
            callback fn;
        }callback_t;
        
        void f0();
        void f1();
        callback_t callbacks[] = {
            { "cmd0", f0},
            {"cmd1", f1},
        }
        
        void f0()
        {
        }
        
        void f1()
        {
        }
    

    2)调用

        void do_callback(const char *name) 
        {
            size_t i;
            for (i = 0; i < sizeof(callbacks) / sizeof(callbacks[0]); i++) {
                if (!strcmp(callbacks[i].name, name)) {
                    return callbacks[i].fn();
               }
            }
        }
    

    这种方式的不便之处在于,当需要映射的函数因分散在不同文件时,每增加一个新的映射都需要修改这个数组,以及头文件。

    2 利用自定义段
    gcc支持通过使用__attribute__((section())),将函数、变量放到指定的数据段中。
    也就是说,可以让编译器帮我们完成1中向数组添加成员的动作。
    借助此机制,回调函数可以在任意文件申明,不需要修改其他文件。
    自定义段的起始和结束地址,可以通过变量__start_SECTIONNAME和__stop_SECTIONNAME得到
    例如通过__attribute__((section("ss"))定义自定义段,其开始地址为&__start_ss,结束地址为&__stop_ss

    以实际代码示例:
    文件a.c:

    #define SEC __attribute__((__section__("ss"), aligned(sizeof(void*))))
    
    void f1 (int a, int b)
    {
        printf("%s %d %d %d
    ", __func__, __LINE__, a, b); 
    }
    
    // 编译器会自动提供__start_ss,__stop_ss标志段ss的起止地址
    extern size_t __start_ss;
    extern size_t __stop_ss;
    
    typedef struct {
        void (*p)(int, int);
    } node_t;
    
    // 结构体变量a位于自定义段ss
    SEC node_t a = { 
        .p = f1, 
    };
    
    int main(int argc, char **argv)
    {
       int a = 0, b = 0;
        node_t *p;
        // 遍历段ss,执行node_t结构中的p指向的函数
        for (p = &__start_ss; p < &__stop_ss;p++) {
            p->p(a, b);
            a+=1;b+=2;
        }
    }
    

    文件b.c:

    #include <stdio.h>
    #define SEC __attribute__((__section__("ss"), aligned(sizeof(void*))))
    
    void ff(int a, int b)
    {
        printf("%s %d %d %d
    ", __func__, __LINE__, a, b); 
    }
    
    typedef struct {
        void (*p)(int, int);
    } node_t;
    
    // 结构体变量m位于自定义段ss
    SEC node_t m = { 
        .p = ff, 
    };
    

    编译指令:
    gcc a.c b.c

    执行结果:
    0x559ae9a88010 0x559ae9a88010 0x559ae9a88030
    f1 8 0 0
    0x559ae9a88028 0x559ae9a88010 0x559ae9a88030
    ff 6 3 6

    https://github.com/pswarfound
  • 相关阅读:
    深刻理解Docker镜像大小
    UVA 12657 Boxes in a Line
    STL 之 iterator traits 备忘
    python设计模式 之 简单工厂模式
    extjs 时间范围选择的实现
    数据结构
    nodeJS npm grunt grunt-cli
    Ubuntu: GlusterFS+HBase安装教程
    ubuntu 休眠之后蓝牙鼠标无效果。
    基于sparksql调用shell脚本运行SQL
  • 原文地址:https://www.cnblogs.com/zl-yang/p/9030058.html
Copyright © 2011-2022 走看看