如何使类型定义的函数的函数指针数组

时间:2019-06-05 16:32:10

标签: c++ embedded arduino-due

我正在尝试实现此库的NeopixelAnimator类:https://github.com/Makuna/NeoPixelBus

我创建了一个动画类,其中包含该库的NeoPixelAnimator类的实例。要运行动画,我必须调用:.StartAnimation(uint16_t indexAnimation, uint16_t duration, UpdateCallback animUpdate)

我的目标是制作一排又一组的动画。第二个动画应在第一个动画完成后开始。由于该库本身不提供执行此操作的方法,因此我创建了一个代表队列的矢量,它包含要进行动画处理的动画及其颜色。

问题在于.StartAnimation()函数需要一个UpdateCallback参数,该参数是一个回调函数,只要调用.UpdateAnimations()函数就被触发。

动画将由连接到Arduino Due的开关触发,该开关调用.add()函数(示例代码中未列出)。现在,我想通过在.init()中添加一个动画来测试它是否有效。

我的计划是创建一个指向这些回调函数的函数指针数组。问题是我无法匹配数据类型。

我们将不胜感激。此外,对于如何解决此类问题以及如何构建代码的反馈也将不胜感激。

我正在将platformIO与Arduino Due板上的Arduino库一起使用。

defines.h:

//Amount of different animations should correspond to the number of callback functions
#define NUMBER_OF_ANIMATIONS 2

//Animation ID's:
#define WIPE_ANIM 0

//Colour ID's:
#define GREEN 0

animator.h:

#include <arduino.h>
#include <NeoPixelAnimator.h>
#include <NeoPixelBrightnessBus.h>
#include <array>
#include <vector>

class Animator
{
public:
private:

//NeoPixel animation time management object
    NeoPixelAnimator animations;

//Neopixel strip communication object
    NeoPixelBrightnessBus<NeoGrbFeature, Neo800KbpsMethod> strip1; //NeoPixel strip 1 object

//Array of AnimUpdateCallback function pointers to the animation callback functions
     AnimUpdateCallback (*_callbackPt[NUMBER_OF_ANIMATIONS])(const AnimationParam &param);

//Vector of arrays to store animations to be animated (animId, colorId)
    std::vector<std::array<uint8_t, 2>> _animationQueue;

public:
    Animator();
    void init();
    void run();
    void add(uint8_t animId, uint8_t colorId);

private:
    void updateQueue();

animator.cpp:

#include <Animator.h>

//Default constructor
Animator::Animator() : strip1(NUMBER_OF_LEDS_1, LED_PIN_1),
                       _callbackPt{wipeColorAnim, wipeColorAnim}
{
}

//Inititalisation function, inits strips, sets brightness for strips, sets inital color with wipeColorAnim()
void Animator::init()
{
    strip1.Begin();

    strip1.SetBrightness(100);

    add(WIPE_ANIM, GREEN);        //wipeColor strip1 with Green
}

//Add aniamtion to the queue
void Animator::add(uint8_t animId, uint8_t colorId)
{
    //Create array storing the animation ID and its color
    std::array<uint8_t, 2> animation{animId, colorId};

    //Add the animation to the end of the queue
    _animationQueue.push_back(animation);
}

//Loop this function to update animations
void Animator::run()
{
    //if there is an animation running
    if (animations.IsAnimating())
    {

        animations.UpdateAnimations(); //update running animation
        strip1.Show();
    }
    else
    {
        updateQueue();
    }
}

//Checks whether there is an animation in the queue if so it's started
void Animator::updateQueue()
{
    //if there is an animation waiting in the queue
    if (!_animationQueue.empty())
    {
        //Start next animation in queue on channel 0 with specified time and animUpdate callback function (channel, time, callback)
        animations.StartAnimation(0, _animationQueue[0][1], _callbackPt[_animationQueue[0][0]]);

        //Remove the just started animation from the queue
        _animationQueue.erase(_animationQueue.begin());
    }
}

main.cpp:

Animator animator;

void setup()
{

    animator.init();
}

void loop()
{
    //Put new animation requests in queue and update animations
    animator.run();
}

platformio.ini:

[env:due]
lib_ldf_mode = chain+
platform = atmelsam
board = due
framework = arduino
monitor_speed = 115200
monitor_port = COM16

lib_deps = 
    NeoPixelBus

调用animations.StartAnimation(0, _animationQueue[0][1], _callbackPt[_animationQueue[0][0]]);不会产生任何编译错误。尝试使函数指针数组中的回调函数无效化

类型“ AnimUpdateCallback (Animator::*)(const AnimationParam &param)”的值不能用于初始化类型“ AnimUpdateCallback (*)(const AnimationParam &param)”的实体

我的主要困惑是:

  • 我的类中的回调函数的数据类型应为(voidAnimUpdateCallback)?

  • 为什么必须在(const AnimationParam &param)的末尾添加(*_callbackPt[NUMBER_OF_ANIMATIONS]),否则我会收到一个错误,即数据类型也不匹配

1 个答案:

答案 0 :(得分:1)

  

类型“ AnimUpdateCallback (Animator::*)(const AnimationParam &param)”的值不能用于初始化类型“ AnimUpdateCallback (*)(const AnimationParam &param)”的实体

是真的。我没有看到导致此错误的代码,但是大概您正在使用Animator的非静态成员函数来初始化数组的元素。 (是wipeColorAnim是什么?成员函数吗?未在问题内声明。)由于非静态成员函数具有隐藏参数(this指针),因此它们与以下对象不兼容:非成员函数。如果您的成员函数不需要this参数,则将其声明为static。 (如果确实需要this,则说明您遇到了更大的设计问题。)

  

我的类中的回调函数的数据类型应该是(voidAnimUpdateCallback)?

好吧,void不是函数类型,所以我想这已经排除了,只剩下一个选择...(除非您是指返回类型,而不是数据类型?数据类型会是函数签名,包括返回类型和参数类型。)

  

为什么必须在(const AnimationParam &param)的末尾添加(*_callbackPt[NUMBER_OF_ANIMATIONS]),否则我会收到一个错误,即数据类型也不匹配

我想一个很好的解释方式是查看声明将声明什么。

 AnimUpdateCallback (*_callbackPt[NUMBER_OF_ANIMATIONS])(const AnimationParam &param);
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <-- an array of pointers

最里面的部分是一个指向某物的指针数组。要查看它们指向的类型,请将最里面的部分压缩为一个星号:

 AnimUpdateCallback (*)(const AnimationParam &param);

这是指向一个函数的指针,该函数采用单个参数(类型为const AnimationParam &)并返回类型为AnimUpdateCallback的值。这里的“ param”标识符是多余的。

没有最后的部分,您只需

 AnimUpdateCallback (*_callbackPt[NUMBER_OF_ANIMATIONS]);
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <-- an array of pointers

这次更容易看到指向类型:AnimUpdateCallback

因此,无论哪种情况,您都可以获取类型AnimUpdateCallback的值。在前一种情况下,您将访问数组的元素,调用其指向的函数,然后查看返回的值,例如:_callbackPt[0](param)。在后一种情况下,您只需访问数组的元素,例如:_callbackPt[0]。正确的格式取决于您打算如何使用此数组。 (NeoPixelAnimator的声明不是直接在问题中,因此我不知道它作为NeoPixelAnimator::StartAnimation()的参数的期望。)