1

对于实时嵌入式系统,我试图提供一个中断处理程序,它允许注册任何非静态方法指针(当然还有对象的实例),当中断发生时,它会被调用。

在 C 中,这很容易做到,例如:

void (*func)(void*) = 0; // <- method to be called goes here
void* instance;          // <- instance for this-call goes here

void InterruptHandler()
{
  func(instance);
}

Afaik,这符合调用非静态方法时 C++ 隐式调用的 this-call。

但是,编译器的 C++ 拒绝将方法指针转换为函数指针(至少我找不到这样做的方法)——这当然是可以理解的,但在我的情况下会适得其反。

有什么方法可以像 C 中那样直接模拟 C++ this-call 吗?我知道委托,但是我的编译器仅限于 C++98,没有 boost 库等;甚至自定义的轻量级实现,例如 Sergey Ryazanov 的 Impossibly Fast C++ Delegates,提供了我希望尽可能避免的一定开销。

4

1 回答 1

2

方法总是包含一个隐藏this参数来提供对被调用对象的访问。要从期望 C 或类 C 调用行为的中断处理程序调用一个类,其中列出的参数和所需参数之间存在 1:1 对应关系,您必须提供该类 C 行为。这意味着没有隐藏参数的自由函数或静态方法。

这意味着您不能在不深入研究未定义行为的假设的情况下将方法分配给函数指针。

但是,如果可以使对象可用,则可以让静态方法或自由函数调用对象上的方法。

给定

void (*func)(void*)

其中void *是指向用户提供的控制信息的指针,简单的解决方案是静态方法或表单的自由函数

void handlerCaller(void* userp)
{
    ISRHandlerClass * handlerp = (ISRHandlerClass *) userp;
    handlerp->isrhandler(); // tiny bit may be lost here to subclass look-up
}

void isrhandler()

被实施以做任何需要做ISRHandlerClass的事情。ISRHandlerClass

您几乎被困在其中handlerCaller或非常喜欢它,因此这是您无法避免的开销。其余的取决于您希望 ISR 接口的通用程度。

一个简单的通用 ISR 处理程序基类:

class ISRHandlerClass
{
    public:
        virtual ~ISRHandlerClass()
        {
        }
        // pure virtual to be implemented by specialized handler
        virtual void isrhandler() = 0;  
};

和一个同样简单的实现者

class FooHandler: public ISRHandlerClass
{
    public:
        void isrhandler() //override tag if you've got 'em
        {
            // read Foo and store in buffer to be processed by lower priority task
        }  
};

但是,如果您想放弃泛化以支持速度,请不要为子类而烦恼。如果您需要多个处理程序调用者,则为多个处理程序调用者牺牲了空间。

void FooHandlerCaller(void* userp)
{
    FooHandler * handlerp = (FooHandler *) userp;
    handlerp->isrhandler();
}

void BarHandlerCaller(void* userp)
{
    BarHandler * handlerp = (BarHandler *) userp;
    handlerp->isrhandler();
}

或者

template <class TYPE>
void handlerCaller(void* userp)
{
    TYPE * handlerp = (TYPE *) userp;
    handlerp->isrhandler();
}

用法

class FooHandler
{
    public:
        void isrhandler()
        {
            // read Foo and store in buffer to be processed by lower priority task
        }  
};

void (*func)(void*) = handlerCaller<FooHandler>;
FooHandler handler;
void* instance = (void *)&handler;
于 2016-07-19T19:49:27.460 回答