首页 > 解决方案 > 如何在c中的另一个函数之前和之后执行公共代码?

问题描述

这里我解释一下问题。假设我在共享内存中加载了一个结构 A。结构 A 可能是这样的:

typedef enum{
    GPIO_1,
    GPIO_2,
    GPIO_3,
    GPIO_4,
    GPIO_5,
    N_GPIO
} gpio;

struct B {
    bool active;
    bool status;
    bool direction;
    int timestamp;
    int t1;
    int t2;
};

struct A {
    struct B gpio[N_GPIO];
};

还假设我有两个函数可以对 A 中的 B 结构之一进行操作:

bool set_status(gpio g, bool status, int t1, int t2);
bool activate(gpio g, bool active);

由于 A 被加载到共享内存中,我需要在上面的两个函数中调用shmgetshmdt ;第一个函数的伪代码应该是这样的:

bool set_status(gpio g, bool status, int t1, int t2) {
    struct A shm = shmget();
    struct B target = shm.gpio[g];
    if(target.active) {
        bool res = foo1(target, status, t1, t2); //do something on struct B indexed by g
        shmdt();
        return res;
    else 
        return false;
}

第二个函数的伪代码应该是这样的:

bool activate(gpio g, bool active) {
    struct A shm = shmget();
    struct B target = shm.gpio[g];
    if(target.active) {
        bool res = foo2(target, active); //do something on struct B indexed by g
        shmdt();
        return res;
    else
        return false;
}

现在,有没有一种方法可以防止拥有管理 shm 并检查是否设置了 B.active 的通用代码?对我来说,这看起来有点像装饰器,即有一个管理 shm 的函数,检查 B.active 并在其中调用第二个函数,但问题是第二个函数可能没有唯一的签名(可能有不同的数字参数)。

我想要这样的东西:

bool set_status(gpio g, bool status, int t1, int t2) {
    return decorator(foo1, g, status, t1, t2); //do something on struct B indexed by g
}

bool activate(gpio g, bool active) {
    return decorator(foo2, g, active); //do something on struct B indexed by g
}

以装饰器管理 shm 并检查目标 B.active 的方式。

谢谢!

编辑:这是一个最小的工作示例,您可以重构 https://github.com/oliviera9/c_decorator

标签: cdesign-patternsstructdecorator

解决方案


您可以创建一个可变参数宏:

#define DECORATOR(fn, g, ...) \
    struct A shm = shmget(); \
    struct B target = shm.gpio[(g)]; \
    if(target.active) { \
        bool res = (fn)(__VA_ARGS__)\
        shmdt(); \
        return res; \
    } else {\
        return false; \
    }

并像这样使用它

bool set_status(gpio g, bool status, int t1, int t2) {
    DECORATOR(foo1, g, status, t1, t2)
}

bool activate(gpio g, bool active) {
    DECORATOR(foo2, g, active)
}

推荐阅读