C中的(伪)OOP从其函数指针获取struct对象

时间:2016-02-13 00:53:19

标签: c oop struct avr avr-gcc

我正在尝试创建自己的小型AVR库。我有想法在代码中使用伪OOP,目前我有"类"定义为结构。我正在考虑是否可以实现类似"这个"关键词。我想在函数指针内部获取struct对象,该函数指针是struct的成员。

我的代码:

#define __class__                   struct
#define __inner_object__            struct

#define ALIAS(cls, stc)             typedef __class__ cls stc
typedef uint8_t     reg8_t;

#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#define container_of(ptr, type, member) ({                      \
    const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
    (type *)( (char *)__mptr - offsetof(type,member) );})

typedef enum {
    PIN_DIR_INPUT  = 0,
    PIN_DIR_OUTPUT = 1
} pin_direction_t;

typedef struct {
    const reg8_t        m_pin;
    const reg8_t        m_ddr;
    const reg8_t        m_port;
    const u1            m_bit;

    void                (*setDirection)(pin_direction_t);
} pin_t;

void __setDirection(pin_direction_t direction)
{
    // how to get struct object here?
    pin_t* pin = container_of(__setDirection, pin_t, setDirection);
    //uint8_t reg = reg_read(pin->m_ddr);
    //if (direction == PIN_DIR_OUTPUT)
        //reg_write(pin->m_ddr, reg | (1uL << pin->m_bit));
    //else
        //reg_write(pin->m_ddr, reg & ~(1uL << pin->m_bit));
}

__class__ at_mega8
{
    __inner_object__
    {
        const reg8_t    REG_PIND;
        const reg8_t    REG_DDRD;
        const reg8_t    REG_PORTD;
        __inner_object__
        {
            const pin_t PIN_D7;
            const pin_t PIN_D6;
            const pin_t PIN_D5;
            const pin_t PIN_D4;
            const pin_t PIN_D3;
            const pin_t PIN_D2;
            const pin_t PIN_D1;
            const pin_t PIN_D0;
        } Pins;
    } PortD;

    __inner_object__
    {
        const reg8_t    REG_PINC;
        const reg8_t    REG_DDRC;
        const reg8_t    REG_PORTC;
        __inner_object__
        {
            const pin_t PIN_C6;
            const pin_t PIN_C5;
            const pin_t PIN_C4;
            const pin_t PIN_C3;
            const pin_t PIN_C2;
            const pin_t PIN_C1;
            const pin_t PIN_C0;
        } Pins;
    } PortC;

    __inner_object__
    {
        const reg8_t    REG_PINB;
        const reg8_t    REG_DDRB;
        const reg8_t    REG_PORTB;
        __inner_object__
        {
            const pin_t PIN_B7;
            const pin_t PIN_B6;
            const pin_t PIN_B5;
            const pin_t PIN_B4;
            const pin_t PIN_B3;
            const pin_t PIN_B2;
            const pin_t PIN_B1;
            const pin_t PIN_B0;
        } Pins;
    } PortB;
};

ALIAS(at_mega8, at_mega8_t);

#define M8_PIND     0x10
#define M8_DDRD     0x11
#define M8_PORTD    0x12

#define M8_PINC     0x13
#define M8_DDRC     0x14
#define M8_PORTC    0x15

#define M8_PINB     0x16
#define M8_DDRB     0x17
#define M8_PORTB    0x18

const at_mega8_t AtMega8 = {
    {
        M8_PIND, M8_DDRD, M8_PORTD,
        {
            { .m_bit = 7, .m_pin = M8_PIND, .m_ddr = M8_DDRD, .m_port = M8_PORTD, .setDirection = __setDirection },
            { .m_bit = 6, .m_pin = M8_PIND, .m_ddr = M8_DDRD, .m_port = M8_PORTD, .setDirection = __setDirection },
            { .m_bit = 5, .m_pin = M8_PIND, .m_ddr = M8_DDRD, .m_port = M8_PORTD, .setDirection = __setDirection },
            { .m_bit = 4, .m_pin = M8_PIND, .m_ddr = M8_DDRD, .m_port = M8_PORTD, .setDirection = __setDirection },
            { .m_bit = 3, .m_pin = M8_PIND, .m_ddr = M8_DDRD, .m_port = M8_PORTD, .setDirection = __setDirection },
            { .m_bit = 2, .m_pin = M8_PIND, .m_ddr = M8_DDRD, .m_port = M8_PORTD, .setDirection = __setDirection },
            { .m_bit = 1, .m_pin = M8_PIND, .m_ddr = M8_DDRD, .m_port = M8_PORTD, .setDirection = __setDirection },
            { .m_bit = 0, .m_pin = M8_PIND, .m_ddr = M8_DDRD, .m_port = M8_PORTD, .setDirection = __setDirection },
        }
    },
    {
        M8_PINC, M8_DDRC, M8_PORTC,
        {
            { .m_bit = 6, .m_pin = M8_PINC, .m_ddr = M8_DDRC, .m_port = M8_PORTC, .setDirection = __setDirection },
            { .m_bit = 5, .m_pin = M8_PINC, .m_ddr = M8_DDRC, .m_port = M8_PORTC, .setDirection = __setDirection },
            { .m_bit = 4, .m_pin = M8_PINC, .m_ddr = M8_DDRC, .m_port = M8_PORTC, .setDirection = __setDirection },
            { .m_bit = 3, .m_pin = M8_PINC, .m_ddr = M8_DDRC, .m_port = M8_PORTC, .setDirection = __setDirection },
            { .m_bit = 2, .m_pin = M8_PINC, .m_ddr = M8_DDRC, .m_port = M8_PORTC, .setDirection = __setDirection },
            { .m_bit = 1, .m_pin = M8_PINC, .m_ddr = M8_DDRC, .m_port = M8_PORTC, .setDirection = __setDirection },
            { .m_bit = 0, .m_pin = M8_PINC, .m_ddr = M8_DDRC, .m_port = M8_PORTC, .setDirection = __setDirection },
        }
    },
    {
        M8_PINB, M8_DDRB, M8_PORTB,
        {
            { .m_bit = 7, .m_pin = M8_PINB, .m_ddr = M8_DDRB, .m_port = M8_PORTB, .setDirection = __setDirection },
            { .m_bit = 6, .m_pin = M8_PINB, .m_ddr = M8_DDRB, .m_port = M8_PORTB, .setDirection = __setDirection },
            { .m_bit = 5, .m_pin = M8_PINB, .m_ddr = M8_DDRB, .m_port = M8_PORTB, .setDirection = __setDirection },
            { .m_bit = 4, .m_pin = M8_PINB, .m_ddr = M8_DDRB, .m_port = M8_PORTB, .setDirection = __setDirection },
            { .m_bit = 3, .m_pin = M8_PINB, .m_ddr = M8_DDRB, .m_port = M8_PORTB, .setDirection = __setDirection },
            { .m_bit = 2, .m_pin = M8_PINB, .m_ddr = M8_DDRB, .m_port = M8_PORTB, .setDirection = __setDirection },
            { .m_bit = 1, .m_pin = M8_PINB, .m_ddr = M8_DDRB, .m_port = M8_PORTB, .setDirection = __setDirection },
            { .m_bit = 0, .m_pin = M8_PINB, .m_ddr = M8_DDRB, .m_port = M8_PORTB, .setDirection = __setDirection },
        }
    },
};

我可以在下面的示例中使用此代码:

hd44780.pinout.pinRS = &AtMega8.PortB.Pins.PIN_B1;
hd44780.init();
// and somewhere else in hd44780:
// rsPin.setDirection(PIN_DIR_OUTPUT);

我知道有container_of宏允许其成员获取容器对象。但是,当我尝试使用此宏时,我收到错误:

  

错误:取消引用指向不完整类型的指针

此错误指向container_of宏定义。

所以,我有两个问题。 是否可以在avr-gcc上的指定函数内获取struct对象?如果不是,是否可以在gcc(windows)上执行此操作?当然,我可以传递struct对象作为参数,但这将是丑陋的

1 个答案:

答案 0 :(得分:1)

简短回答,不 - 用container_of做你想做的事,你需要特定对象中函数指针的地址,而不是它指向的函数的地址,并得到你的' d需要某种指向结构的指针或传递给函数的其中一个成员。

如果你看看C ++正在做什么,它也基本上是一个指向结构的指针。你只是没有看到它发生,因为语言隐藏了你。没有办法解决这个问题,不管怎么说,这个函数必须被告知你希望它与哪个对象一起工作 - 它无法通过魔法知道这一点。