根据构造函数的存在禁用代码

时间:2018-07-20 13:58:44

标签: c++ avr avr-gcc

我正在尝试根据代码是否创建对象(或调用函数等)来禁用某些代码。听起来有些奇怪,我知道。

在我的库中可以创建2个对象,每个对象都需要一个中断服务程序,例如:

ISR(TIMER0_COMPA_vect) {
  // do some stuff if the interrupt happens
}

ISR只能创建一次,但是用户可能只创建一个对象或不创建任何对象,因此,不应首先创建ISR,以免用户阻塞一个对象的创建。 我知道封装这样的代码会很容易

#ifdef OBJECT1
  ISR(TIMER0_COMPA_vect) {
    // do some stuff if the interrupt happens
  }
#endif

但是这迫使用户跟踪她/他创建的对象。 是否可以让预处理器决定是否调用构造函数一次或什至不存在? 有点像这样

Foo:Foo() {
  #define USE_FOO
  //Some code
}

#ifdef USE_FOO
ISR(TIMER0_COMPA_vect) {
  // do some stuff if the interrupt happens
}
#endif

编辑:

根据我得到的答案,我尝试澄清一下我的问题:

Foo1:Foo1() {
    //Some object constructor code
}

Foo2:Foo2() {
    //Some object constructor code
}

ISR(TIMER1_COMPA_vect) {
    //some interrupt code
}

ISR(TIMER2_COMPA_vect) {
    //some interrupt code
}

int main() {
    Foo2 foo2;
}

如果这是我们正在讨论的代码,则根本不应该编译函数ISR(TIMER1_COMPA_vect)。必须缺少ISR。

PS:如果您需要更多信息,我可以提供更多信息,但是我尝试将问题保持在尽可能基本的状态

3 个答案:

答案 0 :(得分:1)

通常,针对这种情况的处理方式是将此类对象的代码编译到库中。链接器足够聪明,可以检测您的主程序是否依赖于库中的任何函数。如果是这样,它将把该函数的整个编译单元(即.c或.cpp文件)加载到您的程序中。它在编译单元中找到的所有ISR都将添加到您的程序中。如果您不使用该库中的任何功能,则不会添加ISR。

例如,在foo1.h中放入如下内容:

#pragma once
class Foo1 {
public:
  Foo1();
};

在foo1.cpp中放入以下内容:

#include <foo1.h>

ISR(TIMER1_COMPA_vect) {
}

Foo1::Foo1() {
}

现在,您应该使用foo1.cppfoo1.o编译成avr-gcc。接下来,使用avr-arfoo1.o存储在名为foo1.a的档案中。然后,使用avr-gcc编译主程序,并提供foo1.a作为参数。确保foo1.a参数位于main.cpp之后。

答案 1 :(得分:0)

正如您所说,您的问题听起来很奇怪,但是如果您只想做一次,让我们说在构造函数中,您可以使用局部静态变量来处理像这样的简单但非常丑陋的事情

Foo:Foo() {
  static bool init = true;
  if( init ) {
    //Some code for ISR init
    init = false;
  }
}

这样,无论您或您的用户构造的Foo对象有多少,您的特殊ISR初始化都只会发生一次

编辑:

我认为没有办法实现自己想要的,至少没有干净的办法。

Imo,您的问题来自您的ISR宏,它实际上有两件事:

  • 初始化您的ISR向量(ISR注册)
  • 定义您的ISR处理程序(ISR处理程序)

要解决您的问题,建议您将其拆分为两个宏,然后:

  • ISR注册进入Foo1 / Foo2构造函数->使用全局字段或任何机制仅初始化一次或在内部跟踪发生的事情
  • 保留仅带有处理程序定义的另一个宏ISR_HANDLER

然后,您的处理程序将保持定义状态,并且如果未由任何Foo类注册,则该处理程序将不受影响

答案 2 :(得分:0)

您可能需要创建一个单例。有很多例子。单例是只构造一次的类。构造函数是私有的,静态方法将检查“全局”变量,以查看是否已经构造了该类(如果没有构造,它将仅构造一次)。您可能需要考虑线程问题,尽管对于构造而言,您可以在创建多个类之前简单地引用该类。对于一个中断的多个用户,您通常使用某种分配器,这些对象向其注册,然后调用对该中断感兴趣的所有类。调度程序可以是单例。通常,调度程序的客户端会实现一个接口。作为向调度程序注册的一部分,该类告诉调度程序其“ this”指针,并且调度程序可以调用从接口实现的方法,就像它们被正常调用一样。客户端不需要具有静态方法。这些东西可能有模式,但我无法命名。