| ??? 06/19/07 16:04 Modified: 06/19/07 16:19 Read: times |
#141025 - Object Oriented Programming in C |
Oliver said:
Once you think OO, even your 8051 C code ends up with an OO design influence. Jan said:
This IS interesting. Can you please elaborate on this? Maybe a short example? (and maybe moving to a new thread, if you agree?) I don't consider myself an "OO thinker" by any stretch, but I do wind up writing some OOP-like C once in a while when it seems to make sense. As an example, the last bit of firmware that I did had to talk to seven UARTs. Two of them were the on-board UARTs on a C8051F120, and the other five were five channels of an external octal UART chip. Being somewhat naturally lazy, and also worried about using up all my code space, I didn't want to duplicate a bunch of code seven times. So I wound up making a UART "class" and seven UART "objects" in C. Here are some snippets that show how I did it. The UART "class definition"
typedef struct {
char rxIn; /* Next empty spot in rxBuff[] */
char rxOut; /* Oldest byte in rxBuff[] */
char *rxBuff; /* Pointer to actual buffer */
char buffSize; /* Buffer size */
} CUartInfo;
Instantiation of seven instances of the class
char trboBuff[TRBO_BUFF_SIZE];
char lasrBuff[LASR_BUFF_SIZE];
char xmotBuff[XMOT_BUFF_SIZE];
char ymotBuff[YMOT_BUFF_SIZE];
char zmotBuff[ZMOT_BUFF_SIZE];
char hostBuff[HOST_BUFF_SIZE];
char dbugBuff[DBUG_BUFF_SIZE];
CUartInfo uarts[] = { /* Array of UART info structures */
{ 0, 0, trboBuff, TRBO_BUFF_SIZE },
{ 0, 0, lasrBuff, LASR_BUFF_SIZE },
{ 0, 0, xmotBuff, XMOT_BUFF_SIZE },
{ 0, 0, ymotBuff, YMOT_BUFF_SIZE },
{ 0, 0, zmotBuff, ZMOT_BUFF_SIZE },
{ 0, 0, hostBuff, HOST_BUFF_SIZE },
{ 0, 0, dbugBuff, DBUG_BUFF_SIZE }
};
A couple of methods
/* ////////////////////////////////////////////////////////////////////////////
CharAvail()
GetChar()
///////////////////////////////////////////////////////////////////////////////
DESCRIPTION: CharAvail() indicates whether or not unread data has
accumulated in the input buffer. GetChar() waits for such data
and returns the oldest character in the buffer.
REVISIONS: 27 Dec 06 - RAC - Adapted from the old kbhit() and getch()
functions
//////////////////////////////////////////////////////////////////////////// */
char CharAvail(char ID) { /* The buffer contains data */
return uarts[ID].rxIn != /* if the in and out */
uarts[ID].rxOut; /* indexes are different */
} /* End CharAvail() */
/* ///////////////////////////////////////////////////////////////////////// */
char GetChar(char ID) {
char rv; /* Put return character here */
while (!CharAvail(ID)) ; /* Wait for a character */
rv = uarts[ID].rxBuff[uarts[ID].rxOut++]; /* Grab byte from rx buffer */
if (uarts[ID].rxOut == uarts[ID].buffSize) { /* Just reached buffer end */
uarts[ID].rxOut = 0; /* Wrap to the beginning */
} /* End 'reached buffer end' */
return rv; /* The answer */
} /* End getch() */
With this setup, a typical method call looks like GetChar(PUMP_UART), rather than pumpUart.GetChar() like you might see in a language with direct OOP support.
A variation on the theme would be to rewrite the methods to accept pointers to the CUartInfo structures instead of indexes into the uarts[] array. That might be a little more efficient, but it would mean everybody and his brother would have pointers to the elements of the uarts[] array, when in fact that information should be accessible only to the methods of the class. There are probably a million ways to do something similar. I would really be interested if Oliver would post what he did, to see how his approach compares to mine. -- Russ |
| Topic | Author | Date |
| Object Oriented Programming in C | 01/01/70 00:00 | |
| Make it ugly. :) | 01/01/70 00:00 | |
| Ugly and scary!!! | 01/01/70 00:00 | |
| Logical approach | 01/01/70 00:00 | |
| Wasn\\\'t Natural For Me | 01/01/70 00:00 | |
| Nice post Russ. | 01/01/70 00:00 | |
| Agree 100% | 01/01/70 00:00 | |
OOP in C | 01/01/70 00:00 | |
| more OO in C | 01/01/70 00:00 | |
| All good hints, for sure | 01/01/70 00:00 |



