c++ - 如何制作类型定义函数的函数指针数组

标签 c++ embedded arduino-due

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

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

我的目标是制作一个接一个动画的队列。第二个动画应该在第一个动画完成后开始。由于库本身不提供执行此操作的方法,我创建了一个表示队列的 vector ,它包含要设置动画的动画及其颜色。

问题是 .StartAnimation() 函数需要一个 UpdateCallback 参数,这是一个回调函数,每当 .UpdateAnimations() 正在调用函数。

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

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

帮助将不胜感激。此外,我们将不胜感激有关如何解决此类问题和构建代码的反馈。

我在 Arduino Due 开发板上将 platformIO 与 Arduino 库结合使用。

定义.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

动画师.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();

动画师.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());
    }
}

主要.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 ¶m)”类型的值不能用于初始化“AnimUpdateCallback (*)(const AnimationParam ¶m)”类型的实体

我的主要困惑是:

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

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

最佳答案

a value of type "AnimUpdateCallback (Animator::*)(const AnimationParam &param)" cannot be used to initialize an entity of type "AnimUpdateCallback (*)(const AnimationParam &param)"

这是真的。我没有看到导致此错误的代码,但推测您正在使用 Animator 的非静态成员函数来初始化数组的元素。 (wipeColorAnim 是什么?一个成员函数?它没有在问题中声明。)由于非静态成员函数有一个隐藏参数(this 指针),它们与非成员函数不签名兼容。如果您的成员函数不需要this 参数,请将其声明为static。 (如果它确实需要 this,那么您的设计问题就更大了。)

what the datatype of the callback functions in my class should be (void or AnimUpdateCallback)?

嗯,void 不是一个函数类型,所以我想那是不可能的,留给你的只有一个选择......(除非你指的是返回类型,而不是数据类型?数据类型将是函数签名,包括返回类型和参数类型。)

why (const AnimationParam &param) has to be added at the end of (*_callbackPt[NUMBER_OF_ANIMATIONS]), otherwise I get an error that the data types are not matching as well

我想解释这一点的一个好方法是查看声明将声明的内容。

 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() 的参数。)

关于c++ - 如何制作类型定义函数的函数指针数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56464605/

相关文章:

c++ - 缓冲输入与标准输入

c - 奇怪的条件

c - 理解这个嵌入式 C 代码

c++ - 将 usart 接收到的 uint8_t* 数据​​与常量字符串进行比较

c++ - 没有调用未解析的重载函数类型的匹配函数

c++ - 如何避免 SDL 2 游戏中的运动模糊?

c++ - cout<<endl;不适用于打印二维数组

android - 如何解决 "section type conflict"编译错误以及将 section 属性与 gcc 结合使用的最佳实践

c++ - 使用 Arduino Due 从 MPU-6050 获取/处理正确的值

c++ - 为什么循环是无限的?