c - (伪)C 中的 OOP 从其函数指针获取结构对象

标签 c oop struct avr avr-gcc

我正在尝试创建自己的小型 AVR 库。我想在代码中使用伪 OOP,目前我将“类”定义为结构。我正在考虑是否可以实现类似“this”关键字的东西。我想在分配给作为结构成员的函数指针的函数中获取结构对象。

我的代码:

#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 宏允许通过其成员获取容器对象。但是当我尝试使用这个宏时,出现了错误:

error: dereferencing pointer to incomplete type

此错误指向 container_of 宏定义。

那么,我有两个问题。 是否有可能在 avr-gcc 上的分配函数中获取结构对象?如果不是,是否可以在 gcc (windows) 上执行此操作?当然,我可以将结构对象作为参数传递,但这会很难看

最佳答案

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

如果您查看 C++ 等在幕后所做的事情,它基本上也是将指针传递给结构。你只是看不到它的发生,因为语言对你隐藏了它。必须以某种方式告知函数您希望它与哪个对象一起工作这一事实是无法解决的 - 它无法通过魔法知道这一点。

关于c - (伪)C 中的 OOP 从其函数指针获取结构对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35374719/

相关文章:

c - 使用 openssl 库验证自签名/过期证书不会返回错误

oop - 在 SmallTalk - Squeak 中打印带有分隔符的集合的正确方法?

delphi - 将 protected 部分中的方法访问限制为少数类

c - 如何使用相同的代码复制在文件中创建的完全相同的结构?

c - 访问结构成员时 valgrind 出现无效读/写错误

c++ - C++类中的公共(public)结构

c - 在 C 中使用 free()

c - 在c中读取字符串时内存覆盖

c - 如何编写单个函数以按行和按列排序的二维数组进行搜索(限制是函数应该类似于 int search(int *A,int n,int key))

java - Java中的强封装和弱封装