C ++ - Как ограничить доступ к глобальной переменной, допуская доступ из подпрограммы обработки прерываний и специализации класса шаблона - PullRequest
0 голосов
/ 10 марта 2020

В настоящее время я работаю с ATmega328p (находится в Arduino Uno) и абстрагируюсь от изменения таблицы векторов прерываний во время выполнения.

Моя проблема заключается в доступности и видимости глобальной переменной g_VectorTable. Я хочу, чтобы он был доступен только из реализации, но не из чего-либо еще. Есть ли способ обойти это, определив переменную как stati c с некоторыми другими модификациями? (Реализация по специализации должна остаться, ее можно переместить в .tcc файлы, реструктурировать и т.д. c.)

Я знаю, что глобальная переменная не является решением. Я ищу конструкцию, которая позволяет мне получить доступ к этому массиву из подпрограммы обработки прерываний, а также из специализации шаблона, ограничивая доступ ко всему остальному.

Текущее состояние моего проекта:

интерфейс <hal/InterruptVectorTable.hpp>:

template <class Impl, class IRQType>
class InterruptVectorTable
{
  private:
    InterruptVectorTable();
  public:
    InterruptVectorTable(InterruptVectorTable const&) = delete;
    void operator=(InterruptVectorTable const&) = delete;
    static auto getInstance() -> InterruptVectorTable&;
    auto setISR(IRQType InterruptIndex, void (*Callback)(void)) -> void;
};

Реализация по специализации InterruptVectorTable.hpp:

extern void (*g_VectorTable[26])(void);
template <>
class InterruptVectorTable<DeviceAtMega328p, IRQType> // IRQType is an enum class
{
  private:
    InterruptVectorTable()
    {
        auto DefaultHandler = []() -> void {};

        g_VectorTable[0] = 0x0;

        for (uint8_t i = 1; i < 26; i++)
        {
            g_VectorTable[i] = DefaultHandler;
        }
        m_VectorTable = reinterpret_cast<uint8_t*>(g_VectorTable);
    }
    uint8_t* m_VectorTable;

   public:

    static auto getInstance() -> InterruptVectorTable&
    {   
        static InterruptVectorTable instance;
        return instance;
    }

    auto setISR(IRQType InterruptIndex, void (*Callback)(void)) -> void
    {
        g_VectorTable[static_cast<uint8_t>(InterruptIndex)] = Callback;
    }
    // ...
};

Реализация InterruptVectorTable.cpp:

#include <avr/interrupt.h>

void (*g_VectorTable[26])(void) = {0x0, };

ISR(INT0_vect)
{
    g_VectorTable[1]();
}
ISR(INT1_vect)
{
    g_VectorTable[2]();
}
ISR(PCINT0_vect)
{
    g_VectorTable[3]();
}
ISR(PCINT1_vect)
{
    g_VectorTable[4]();
}
// ...

Ответы [ 2 ]

1 голос
/ 10 марта 2020

Если вы не можете изменить такую ​​глобальную переменную, теперь есть способ ограничения области действия глобальной переменной в C ++.

0 голосов
/ 01 мая 2020

Ответ на эту проблему:

разбить специализацию на две части:
- часть первая: определение специализации в заголовочном файле.
- часть вторая: реализация специализация в cpp файле

Часть первая (InterruptVectorTable.hpp):

template <>
class InterruptVectorTable<DeviceAtmega328p, IRQType>
{
  private:
    InterruptVectorTable();
  public:
    InterruptVectorTable(InterruptVectorTable const&) = delete;
    void operator=(InterruptVectorTable const&) = delete;
    static auto getInstance() -> InterruptVectorTable&;
    auto setISR(IRQType InterruptIndex, void (*Callback)(void)) -> void;
};

Часть вторая (InterruptVectorTable.cpp):

#inlcude "InterruptVectorTable.hpp"

static void (*s_VectorTable[26])(void);

ISR(INT0_vect)
{
    g_VectorTable[1]();
}
// ...

auto InterruptVectorTable<DeviceAtmega328p, IRQType>::setISR(IRQType InterruptIndex, void (*Callback)(void)) -> void {
    s_VectorTable[static_cast<int>(IRQType)] = Callback;
}
//...

Последняя необходимо поместить определение переменной в исходный файл. cpp (см. выше) и пометить его как static, чтобы скрыть от внешнего доступа, находясь в глобальной области видимости.

...