2017-07-19 72 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)這是返回一個函數指針的另一種方式。