Я пытаюсь создать свою собственную небольшую библиотеку AVR. У меня есть идея использовать псевдо ООП в коде, и в настоящее время у меня есть «классы», определенные как структуры. Я рассматриваю, возможно ли реализовать что-то вроде этого «ключевого слова». Я хочу, чтобы объект struct внутри функции был назначен указателю на функцию, который является членом struct.(pseudo) OOP в C Получить объект 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
макрос, который позволяет получить объект контейнера его членом. Но когда я пытаюсь использовать этот макрос я получаю сообщение об ошибке:
error: dereferencing pointer to incomplete type
Эта ошибка указывает на container_of
макроопределения.
Итак, у меня есть два вопроса. Возможно ли получить объект struct внутри назначенной функции на avr-gcc? Если нет, можно ли это сделать на gcc (windows)? Конечно, я мог бы передать объект struct, чтобы функционировать как paramater, но это было бы уродливо.
Благодарим за ответ. Я думаю, что я могу остаться в пути, чтобы передать указатель объекта структуры для функции в качестве параметра. Я попытаюсь реализовать кучу, и, возможно, я каким-то образом получаю объект struct из функции. Спасибо за совет. – shjeff