Go Down

Topic: Comments requested on tutorial for function pointers (Read 5142 times) previous topic - next topic


I'm cooking a sort-of roast turkey,

None of your tutorials is a Turkey :)

I understand what you say about the idiosyncrasy but what caught my eye was that you seemed to have two identical lines of code and at first I thought one of them was a mistake. Alas, I stand by my view that an explanation is needed for example

"The previous line is a prototype (see function prototype) for the following function and is required to keep the Arduino compiler happy. Most of the time  the Arduino IDE is able to figure this sort of thing out for itself - but because function pointers are a little more complex we need to give it a helping hand"

Feel free to re-write in your own style.

Two or three hours spent thinking and reading documentation solves most programming problems.


Post amended incorporating your suggestions in one form or another. ;)

New short link:

Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics


Hi Nick, good job re function pointers at gammon.com.au - as always. I thought I'd make a couple of suggestions.

1. you might spend a little more time defining what "callback" or "callback function" really means; the term itself and its possible uses are a little bit equivocal.

2. secondly, you mentioned the IDE using callbacks in various libraries, but it might be useful to add a section showing how to actually do that.

I recently "tried" to use a 3rd party library that had such a callback function. Unfortunately the library is riddled with bugs, and appeared to never have worked at all [as also evidenced by having ZERO examples included]. However, the callback function code does seem to work ok. I'm including the entire functions below, but it's easy to abstract out the pertinent details. The really nice thing here is, you can write your own callback fcn in your sketch to take the data that is being received in the library as multiple successive packets [upwards to 100s] and store it to any place you want, packet receipt by packet receipt. In this case, it goes onto an SD Card, but could go into a RAM buffer, EEPROM, out another port, etc. All in all, I thought the entire process was pretty darn cool, even if the library was hash.

Code: [Select]
1. in the program, the callback fcn writes the data in holdBuff to the SD card.
   holdBuff is filled by the library fcn.

/* Each call to _callback() in the library functions will transfer one
   data packet from the temporary holding buffer [holdBuff] and append
     to the SD file until entire image [of picSize bytes] has been
  params: ALL params are values to be filled in by call to _callback().
      holdBuff = points to holding buffer containing current image block.
        picStartPos not used here.
void sdPic_callback( uint32_t picSize, uint32_t picStartPos,
  uint16_t dataSize, byte* holdBuff )
  sdFile.write(holdBuff, dataSize);
  writtenPicSize += dataSize;
  Serial.print("\n>SD picture write ");
  if( writtenPicSize >= picSize) {
    Serial.println("... Success");
  else {  Serial.println("... FAILURE");  }

2. in the program, this is where it calls the library fcn; it passes a pointer
    to [ie the address of] the callback fcn here.

  // transfer picture into SD card.
  if( cam.getJPEGPicture(PT_JPEG,procDelay,&sdPic_callback) )
    Serial.println(">get JPEG Picture ok");
  else  return;

3. in the library, this is where it calls the callback fcn; it uses a pointer
    to a callback fcn as an input parameter.

The big advantage here is that this fcn has a big loop that grabs N
data packets from the jpeg camera, and uses the callback fcn from
the main program to write the data to the SD card [or anywhere
else that you want to write it]. Alternatively, without the callback
you'd have to code this loop yourself out in the main program.

bool CameraC328R::getJPEGPictureData( uint32_t picSize, uint16_t processDelay,
   void (*callback)(uint32_t picsize, uint32_t picstartpos,
           uint16_t datalen, byte* holdbuff) )
  // vars used locally.
  uint8_t  errCount=0;     // keeps track of #errors, up to MAX_ERRORS.
  uint32_t picDataPos=0;   // current byte position in ENTIRE image.
  bool packSuccess;
    // vars passed back to callback().
  uint16_t dataSize=0;          // size of picture data within the package.   
  byte holdBuff[_packageSize];  // holding buffer for camera data, 64(typ).
  uint16_t packCount=0;         // keeps track of #packages received.

  // track errors during data transfer.
  while( (picDataPos < picSize) && (errCount < MAX_ERRORS) ) {
    sendACK(0, packCount);
    delay( PACKAGE_DELAY );   // allow time to process, transmit data

    // wait for the next package from the camera.
    packSuccess=waitForData(processDelay, holdBuff, _packageSize);

    if( packSuccess ) {
      // this is the size of the picture data within the package
      dataSize  = (holdBuff[3] << 8) + holdBuff[2];

      // execute callback
      callback( picSize, picDataPos, dataSize, (holdBuff+PAC_DATA_START) );
      picDataPos += dataSize;  // advantage index in image.
    else {  errCount++;  }
  sendACK(0, LAST_JPEG_ACK);    // send last ACK.

  if( errCount < MAX_ERRORS)  return true;
    else  return false;


Thanks for the comments. I'm not sure what else I can say about callback functions unless I can find a suitable link.*

I'm  trying to to over-complicate the post with very busy examples, but I also don't want it to be so simple it doesn't cover real-world applications.

* Added a link to Wikipedia, and added another example of using them, this time using qsort.
Please post technical questions on the forum, not by personal message. Thanks!

More info: http://www.gammon.com.au/electronics


Sep 25, 2014, 08:19 am Last Edit: Sep 25, 2014, 06:25 pm by oric_dan Reason: 1
The link helps, I think. My feeling when looking at your page initially, was what exactly is the difference between a pointer to function and a callback? In regards overcomplication, I posted the entire library fcn for reference, but it can easily be reduced to its fundamental details. And the basic idea between give and take described. In any case, I'm only making "suggestions", you don't need to take them too seriously :-). I just know I learned a huge amount from this example, even if the library never worked properly.

Code: [Select]
*  misc handshake and error checking is left out for clarity.
bool CameraC328R::getPictureData( void (*callback)(uint32_t startpos, uint16_t datalen, byte* buff) )
  .... (declare local variables) ....
  byte holdBuff[64];                 // holding buffer for camera data.

 // access sequence of data packets, and transfer to calling sketch using callback.
 while( !end_of_image() ) {
   if( waitForData(holdBuff) ) {                  // wait for the next data packet.  
     callback( picDataPos, 64, holdBuff );    // transfer to main program.

     .... (perform requisite handshakes, indexing, and error-checking) ....

     picDataPos += 64;  // advance index in image.

Go Up