Gernot Frisch said:
since C does not support construcor functions for structs, what is the
usual approach to write this C++ code in C:
Code:
struct foo
{
foo() {bar=0;}
int bar;
};
int main()
{
foo f[5];
}
I would write:
Code:
struct foo
{
bar;
};
Init(foo& f)
{
bar=0;
}
int main(int, char**)
{
foo f[5];
// Put this in a Macro: INIT(f)?
for(int i=0; i<sizeof(f)/sizeof(f[0]); ++i)
Init(f[i]);
return 0;
}
Any better ideas?
Yes. Do you own "C with classes" as C-front did. Include methods in
the structure as function pointers, with an explicit parameter for the
struct itself. (Replacing "this".)
struct foo
{
int bar;
void (*init)(struct foo* this);
};
int main()
{
struct foo f;
...
f.init(&f);
}
Similar code from a real project:
( Notes: was(Un)formatted to fit here, will not compile as-is, several
typedefs and definitions missing.)
============================
//--------------------------------------------------------------
// message descriptor structure
//--------------------------------------------------------------
typedef struct msg_desc msg_desc_s;
struct msg_desc
{
msg_type_e type; // <- Message type (id for
// internal system transfers).
uint16_t code; // <- Message code (id for on-the
// -wire transfers).
uint16_t code_mask;// <- Bit mask to extract code.
char *name; // <- Message name. For debugging
// only, can be removed if we
// run short of memory.
bool (*init)(msg_desc_s const * const desc);
// ^- Initialization function.
bool (*encode)(prv_msg_s * prv_msg,
const ccs_msg_s * app_msg);
// ^- Message encoding function.
bool (*decode)(ccs_msg_s * app_msg,
const prv_msg_s * prv_msg);
// ^- Message decoding function.
bool (*time_update)(isr_msg_s * isr_msg);
// ^- Time update function. Called
// by the transmit ISR immediately
// before delivering a message to
// the FPGA. NULL for
// messages that do not carry
// timing information
bool (*insert)(prv_msg_s * fifo,
const prv_msg_s * prv_msg);
// ^- Function to insert message
// in transmit fifo.
// Normally points to fifo_insert(),
// but can be replaced to implement
// message type specific fifo
// bumping/replacement policies.
uint16_t leng; // <- Message length.
uint16_t repeat; // <- Number of time message should be
// repeated.
uint16_t flags; // <- Message flags. //%TODO% - define,
// remove?
bool keep; // <- If true do not remove from
// fifo after transmission (for
// messages that need
// acknowledgement, etc.)
prv_msg_s *fifo; // <- Pointer to per type message
// transmit fifo.
uint16_t fifo_size;// <- Fifo size. Today all fifos
// are of size COM_TX_FIFO_SIZE.
// This is a place holder to
// allow per-message-type fifo
// sizes in the future.
uint16_t ttl; // <- Message time to live. If a
// message remains in a transmit
// fifo longer than this time,
// (most likely because of higher
// priority messages being
// transmitted ahead of it,) it
// will be deleted.
bool can_abort;// <- If true, message transmition
// can be aborted when higher
// priority messages are pending.
// Valid only for messages of
// leng > 1 - (*NOT* used yet)
uint16_t rx_mbx; // <- Receive mailbox index
uint16_t msg_delay;// <- Minimum intermessage delay
bool (*tx_process)(const prv_msg_s * prv_msg);
// ^- Called before transmision for
// message-specific post-processing.
// NULL if not needed
bool (*rx_process)(ccs_msg_s * app_msg,
const prv_msg_s * prv_msg);
// ^- Called after receiving for
// message-specific post-processing
// NULL if not needed
msg_stats_s *stats; // <- Per-message statistics block
};
============================
Sample usage:
msg_desc_s *desc = ...;
bool stat;
....
// encode message
stat = (desc->encode)(com1_tx_prv_msg, com1_tx_app_msg);
// encoding errors ?
if (!stat)
{
// yes, update error counters & exit
desc->stats->txtsk_encode_errors++;
continue;
}
// call post-process function if neccessary
if (desc->tx_process)
{
stat = (desc->tx_process)(com1_tx_prv_msg);
// post-process errors?
if (!stat)
{
// yes, update error counters and exit
// without updating transmit fifos
desc->stats->txtsk_process_errors++;
continue;
}
}
// insert in fifo for transmission
stat = (desc->insert)(desc->fifo, com1_tx_prv_msg);
// insertion failed ?
if (!stat)
{
// yes, update error counters & exit
desc->stats->txtsk_fifo_insert_errors++;
continue;
}
....