2017-07-19 89 views
-2

我想编辑我的文章并询问函数回调及其在程序功能中的应用,特别是在嵌入式系统应用程序的情况下。在C和C++中具有不同配置的函数指针

我的工作是在twi的AVR库上,我实际上做了我自己的I2C库,但我的代码中有一个错误,但我不知道实际问题在哪里。

我对我的项目有2个库,但我想要做的是分别为AVR和Arduino包装一个twi和wire库的副本。看看问题在哪里,因为这是我计划发现错误并提高C编码技能的计划。

我目前关心的是twi和wire库中的回调函数以及两个库之间的关系。

我会包含来自twi和wire库的行。但我也对回调函数的概念和它们的优点感兴趣。

首先,我将与TWI库开始:

twi.h

我所知道的是,这些都是接收函数指针的函数的声明,但什么是目的接收函数指针?我知道你可以开发函数指针并将函数传递给它们以获得更多功能,但是为什么函数接收函数指针呢?它是如何工作的?

void twi_attachSlaveRxEvent(void (*)(uint8_t*, int)); 
void twi_attachSlaveTxEvent(void (*)(void)); 

twi.c

我觉得这两条线是函数指针的声明,您可以通过正常的功能更多的功能。

static void (*twi_onSlaveTransmit)(void); 
static void (*twi_onSlaveReceive)(uint8_t*, int); 

但是,如果这些都是twi.h中的声明,那为什么这两个函数指针呢?他们可以接收哪些功能?我可以在这里做什么优点?

#ifndef twi_h 
#define twi_h 

    #include <inttypes.h> 

    //#define ATMEGA8 

    #ifndef TWI_FREQ 
    #define TWI_FREQ 100000L 
    #endif 

    #ifndef TWI_BUFFER_LENGTH 
    #define TWI_BUFFER_LENGTH 32 
    #endif 

    #define TWI_READY 0 
    #define TWI_MRX 1 
    #define TWI_MTX 2 
    #define TWI_SRX 3 
    #define TWI_STX 4 

    void twi_init(void); 
    void twi_disable(void); 
    void twi_setAddress(uint8_t); 
    void twi_setFrequency(uint32_t); 

    uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t, uint8_t); 
    uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t, uint8_t); 
    uint8_t twi_transmit(const uint8_t*, uint8_t); 

    void twi_attachSlaveRxEvent(void (*)(uint8_t*, int)); 
    void twi_attachSlaveTxEvent(void (*)(void)); 
    void twi_reply(uint8_t); 
    void twi_stop(void); 
    void twi_releaseBus(void); 

#endif 

这些都是函数定义,我在这里可以理解的是,第一个是接收一个函数指针返回自认倒霉2个ARGS功能。第二个是用于接收一个函数指针函数返回什么没有ARGS

/* 
* Function twi_attachSlaveRxEvent 
* Desc  sets function called before a slave read operation 
* Input function: callback function to use 
* Output none 
*/ 
void twi_attachSlaveRxEvent(void (*function)(uint8_t*, int)) 
{ 
    twi_onSlaveReceive = function; 
} 

/* 
* Function twi_attachSlaveTxEvent 
* Desc  sets function called before a slave write operation 
* Input function: callback function to use 
* Output none 
*/ 
void twi_attachSlaveTxEvent(void (*function)(void)) 
{ 
    twi_onSlaveTransmit = function; 
} 

其次,在电线库:

wire.h

接下来的四个线是声明功能;前两个用于函数指针,后两个是正常的函数声明。

static void (*user_onRequest)(void); 
static void (*user_onReceive)(int); 
static void onRequestService(void); 
static void onReceiveService(uint8_t*, int); 

wire.cpp

现在,这些都在.cpp文件中的函数的定义,我其实不明白它们是如何工作的,什么是这些功能的卷,更重要的问题是它们是如何与twi图书馆相关和包装的?

我真的很感谢我的担忧和答案,因为我认为理解这些库对理解AVR和Arduino平台的其他代码和库非常有用。

// behind the scenes function that is called when data is received 
void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes) 
{ 
    // don't bother if user hasn't registered a callback 
    if(!user_onReceive){ 
    return; 
    } 
    // don't bother if rx buffer is in use by a master requestFrom() op 
    // i know this drops data, but it allows for slight stupidity 
    // meaning, they may not have read all the master requestFrom() data yet 
    if(rxBufferIndex < rxBufferLength){ 
    return; 
    } 
    // copy twi rx buffer into local read buffer 
    // this enables new reads to happen in parallel 
    for(uint8_t i = 0; i < numBytes; ++i){ 
    rxBuffer[i] = inBytes[i];  
    } 
    // set rx iterator vars 
    rxBufferIndex = 0; 
    rxBufferLength = numBytes; 
    // alert user program 
    user_onReceive(numBytes); 
} 

// behind the scenes function that is called when data is requested 
void TwoWire::onRequestService(void) 
{ 
    // don't bother if user hasn't registered a callback 
    if(!user_onRequest){ 
    return; 
    } 
    // reset tx buffer iterator vars 
    // !!! this will kill any pending pre-master sendTo() activity 
    txBufferIndex = 0; 
    txBufferLength = 0; 
    // alert user program 
    user_onRequest(); 
} 

// sets function called on slave write 
void TwoWire::onReceive(void (*function)(int)) 
{ 
    user_onReceive = function; 
} 

// sets function called on slave read 
void TwoWire::onRequest(void (*function)(void)) 
{ 
    user_onRequest = function; 
} 
+3

2.是一个接受函数指针的函数,4.是一个返回函数指针的函数 –

+0

我们不是一个辅导服务。你的问题太广泛了。一本好的C书会有所帮助。 – Olaf

+0

好的,对不起,我实际上得到了函数指针,是因为我在AVR twi库中找到的函数指针,这个函数指针包裹在Arduino的线库中,所以这些函数指针对我来说还是不清楚,并且想知道函数的作用是什么对事件感兴趣的回调。 –

回答

3
  1. 同普通typdefs,2和非常有用4.输入而是整个事情的,你现在可以使用myFuncDef
  2. 函数声明为临危一个函数指针的函数。函数指针为1的函数将看起来像int add2to3(myFuncDef functionPtr);
  3. -
  4. 函数接受一个int和(可能基于该函数)返回给你一个函数指针。使用的typedef它会看起来像myFuncDef functionFactory(int n);

没有的typedef这些链指针的指针可以得到令人难以置信的,只要能在这个问题上可以看出:C syntax for functions returning function pointers

+1

UV'd,'typedef'确实是一种很好的习惯来保持这种代码*对于人类来说是有点可读的;) –

+0

是的,感谢你的链接,指针的扩展以及与大括号和星星的关系看起来很简单,但真的是如何在现实生活中起作用?对于达到处理函数指针的级别来说,这应该是非常棒的,并且看看它们如何强大。 –

0

类型定义(一个或多个)用于简化声明。

此声明

int add2to3(int (*functionPtr)(int, int));  

它声明作为参数的指针的函数与该类型int的两个参数,并且具有返回类型int的功能。

为了使此声明更简单,您可以将参数编写为具有函数类型而不是指向函数的类型指针。

int add2to3(int function(int, int)); 

或者您可以使用typedef的

typedef int (*myFuncDef)(int, int);  

//... 

int add2to3(myFuncDef functionPtr); 

这个声明

int (*functionFactory(int n))(int, int); 

声明了类型int的一个参数,具有返回类型指向函数的函数具有int类型的两个参数并且具有返回类型int

再次使用的typedef上面可以简化申报

typedef int (*myFuncDef)(int, int);  

//... 

myFuncDef functionFactory(int n); 
1

1)函数指针的typdef将有助于从一个函数返回一个函数指针。
即,typedef int (*myFuncDef)(int, int);
myDuncDef retFunc()这里retFunc返回函数指针。

2)int add2to3(int (*functionPtr)(int, int));这里add2to3函数获取指定类型的函数指针作为参数。

3)------

4)int (*functionFactory(int n))(int, int)这是返回一个函数指针的另一种方式。