Languages/C/SplitCH

From UIT
(Difference between revisions)
Jump to: navigation, search
(Created page with "{{TOC right}} = Source and header file split = It is sometimes complicated to split the header and the source file, here are some hints: * The header MUST contain what is nec...")
 
(Source and header file split)
 
(29 intermediate revisions by 4 users not shown)
Line 1: Line 1:
 
{{TOC right}}
 
{{TOC right}}
 
= Source and header file split =
 
= Source and header file split =
 
 
It is sometimes complicated to split the header and the source file, here are some hints:
 
It is sometimes complicated to split the header and the source file, here are some hints:
* The header MUST contain what is necessary from the '''outside''' of the source file.
+
 
* The header SHOULD NOT contain, what is not necessary.
+
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED",  "MAY", and "OPTIONAL" in this document are to be interpreted as described in [https://www.ietf.org/rfc/rfc2119.txt RFC 2119].
 +
 
 +
* (1) The header MUST contain what is necessary from the '''outside''' of the source file.
 +
* (2) The header SHOULD NOT contain, what is not necessary.
 
** There is no reason to pollute the namespace of the whole project.
 
** There is no reason to pollute the namespace of the whole project.
** Keeping the interface small and as clean as possible will make team work simpler.
+
** Keeping the interface small and as clean as possible will make team work simplier.
* The header file MUST prevent multiple inclusion
+
** Including only the necessary headers will shorten (re-)compilation time.
* A header file SHOULD be complete (it defines or includes all it needs).
+
* (3) The header file MUST prevent multiple inclusion, by using ''include guards''.
** Example, if you use a uint32_t parameter in a function, the header should include <stdint.h>
+
* (4) A header file SHOULD be complete (it defines or includes all it needs).
* A header file SHOULD not include files only used in source file
+
** Example, if you use a uint32_t parameter in a function, the header should include <stdint.h>.
* The header SHOULD be commented enough so there is no need to open the source file.
+
** This can be tested by compiling a empty C file only including the header.
* The source file MUST include the header
+
* (5) A header file SHOULD not include files only used in source file.
** This will ensure constistency
+
* (6) The header SHOULD be commented enough so there is no need to open the source file.
 +
** A consistent commenting SHOULD be used, for instance [http://www.doxygen.org doxygen] style.
 +
* (7) The source file MUST include the header, preferably first.
 +
** This will ensure consistency and (4)
 +
* (8) All symbols not exported by the header SHOULD be static (functions and variables).
 +
** This will prevent namespace pollution
 +
** Free benefit: the compiler can do better optimization (automatic inline, ...)
 +
* (9) C headers SHOULD be C++ friendly ("export C")
 +
** Without this C++ application can't link against C files
 +
 
 
== Temperature sensor example ==
 
== Temperature sensor example ==
Here is a simple main :
 
  
{|class=wikitable
+
Here is a small example, using <code>main.c</code>, <code>temp_sensor.h</code>, and <code>temp_sensor.c</code>.
|-
+
 
 +
* <code>temp_sensor.c</code> Contains the code for accessing a fictional temperature sensor.
 +
* <code>temp_sensor.h</code> Defines the software interface for the temperature sensor.
 +
* <code>main.c</code> Will display the current temperature.
 +
 
 +
=== main.c ===
 
<source lang='c'>
 
<source lang='c'>
 +
#include "temp_sensor.h"
 
#include <stdio.h>
 
#include <stdio.h>
#
+
 
 +
int main(int argc, char *argv[])
 +
{
 +
printf("temperature is : %d", temp_sensor_get());
 +
return 0;
 +
}
 +
 
 +
</source>
 +
 
 +
=== temp_sensor.h ===
 +
 
 +
<source lang='c'>
 +
/**
 +
* \file temp_sensor.h
 +
*
 +
* \brief Temperature sensor driver
 +
*/
 +
#ifndef TEMP_SENSOR_H // (3) prevent multiple inclusion, see the #endif at the end of the file
 +
#define TEMP_SENSOR_H
 +
 
 +
#ifdef __cplusplus // (9) C++ friendly export, see the corresponding closing brace
 +
extern "C" { // This brace must contain every functions and variables declaration
 +
#endif
 +
 
 +
#include <stdint.h> // (4) We use stdint in the interface !
 +
 
 +
// (6) Full comments, no need to open temp_sensor.c
 +
// (1) This function is needed in main
 +
/**
 +
* \brief Get the temperature
 +
*
 +
* \return the temperature in K.
 +
*
 +
* \warning the value will be 0 if the sensor read fails.
 +
*/
 +
uint16_t temp_sensor_get(void);
 +
 
 +
#ifdef __cplusplus
 +
}
 +
#endif
 +
 
 +
#endif /* TEMP_SENSOR_H */
 +
</source>
 +
 
 +
=== temp_sensor.c ===
 +
 
 +
<source lang='c'>
 +
/**
 +
* \file temp_sensor.c
 +
*
 +
* \brief Temperature sensor driver implementation
 +
*/
 +
 
 +
#include "temp_sensor.h" // (7) Include the header for compile-time checks
 +
#include <super_os/i2c.h> // (5) The i2c bus is not used in main, so it is included in this .c file, not in the .h
 +
 
 +
// (2) These defines are private, we don't want to see them in main
 +
#define SENSOR_ADDRESS 0x12
 +
#define SENSOR_REG 0x33
 +
 
 +
// (8) this function is not exported -> static
 +
// (6) this function MUST be commented here
 +
/**
 +
* \brief Do the real work here
 +
* \param chip, the i2c address of the chip
 +
* \param address, the address in the chip
 +
* \param value, where to store the value
 +
* \return 0 for no problem
 +
*/
 +
static uint8_t read(uint8_t chip, uint8_t address, uint16_t *value)
 +
{
 +
if (i2c_read(chip, address, value, 2) != 0)
 +
{
 +
return 1;
 +
}
 +
 
 +
return 0;
 +
}
 +
 
 +
// (6) This function is already commented in the header
 +
uint16_t temp_sensor_get(void)
 +
{
 +
uint16_t temp;
 +
uint8_t status = read(SENSOR_ADDRESS, SENSOR_REG, &temp);
 +
 
 +
// Do what is said in temp_sensor.h
 +
if (status != 0)
 +
{
 +
temp = 0;
 +
}
 +
 
 +
return temp;
 +
}
 +
 
 
</source>
 
</source>
|}
 

Latest revision as of 09:48, 31 March 2016

Contents

Source and header file split

It is sometimes complicated to split the header and the source file, here are some hints:

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.

  • (1) The header MUST contain what is necessary from the outside of the source file.
  • (2) The header SHOULD NOT contain, what is not necessary.
    • There is no reason to pollute the namespace of the whole project.
    • Keeping the interface small and as clean as possible will make team work simplier.
    • Including only the necessary headers will shorten (re-)compilation time.
  • (3) The header file MUST prevent multiple inclusion, by using include guards.
  • (4) A header file SHOULD be complete (it defines or includes all it needs).
    • Example, if you use a uint32_t parameter in a function, the header should include <stdint.h>.
    • This can be tested by compiling a empty C file only including the header.
  • (5) A header file SHOULD not include files only used in source file.
  • (6) The header SHOULD be commented enough so there is no need to open the source file.
    • A consistent commenting SHOULD be used, for instance doxygen style.
  • (7) The source file MUST include the header, preferably first.
    • This will ensure consistency and (4)
  • (8) All symbols not exported by the header SHOULD be static (functions and variables).
    • This will prevent namespace pollution
    • Free benefit: the compiler can do better optimization (automatic inline, ...)
  • (9) C headers SHOULD be C++ friendly ("export C")
    • Without this C++ application can't link against C files

Temperature sensor example

Here is a small example, using main.c, temp_sensor.h, and temp_sensor.c.

  • temp_sensor.c Contains the code for accessing a fictional temperature sensor.
  • temp_sensor.h Defines the software interface for the temperature sensor.
  • main.c Will display the current temperature.

main.c

#include "temp_sensor.h"
#include <stdio.h>
 
int main(int argc, char *argv[])
{
	printf("temperature is : %d", temp_sensor_get());
	return 0;
}

temp_sensor.h

/**
 * \file temp_sensor.h
 *
 * \brief Temperature sensor driver
 */
#ifndef TEMP_SENSOR_H // (3) prevent multiple inclusion, see the #endif at the end of the file
#define TEMP_SENSOR_H
 
#ifdef __cplusplus // (9) C++ friendly export, see the corresponding closing brace
extern "C" { // This brace must contain every functions and variables declaration
#endif
 
#include <stdint.h> // (4) We use stdint in the interface !
 
// (6) Full comments, no need to open temp_sensor.c
// (1) This function is needed in main
/**
 * \brief Get the temperature
 *
 * \return the temperature in K.
 *
 * \warning the value will be 0 if the sensor read fails.
 */
uint16_t temp_sensor_get(void);
 
#ifdef __cplusplus
}
#endif
 
#endif /* TEMP_SENSOR_H */

temp_sensor.c

/**
 * \file temp_sensor.c
 *
 * \brief Temperature sensor driver implementation
 */
 
#include "temp_sensor.h" // (7) Include the header for compile-time checks
#include <super_os/i2c.h> // (5) The i2c bus is not used in main, so it is included in this .c file, not in the .h
 
// (2) These defines are private, we don't want to see them in main
#define SENSOR_ADDRESS 0x12
#define SENSOR_REG 0x33
 
// (8) this function is not exported -> static
// (6) this function MUST be commented here
/**
 * \brief Do the real work here
 * \param chip, the i2c address of the chip
 * \param address, the address in the chip
 * \param value, where to store the value
 * \return 0 for no problem
 */
static uint8_t read(uint8_t chip, uint8_t address, uint16_t *value)
{
	if (i2c_read(chip, address, value, 2) != 0)
	{
		return 1;
	}
 
	return 0;
}
 
// (6) This function is already commented in the header
uint16_t temp_sensor_get(void)
{
	uint16_t temp;
	uint8_t status = read(SENSOR_ADDRESS, SENSOR_REG, &temp);
 
	// Do what is said in temp_sensor.h
	if (status != 0)
	{
		temp = 0;
	}
 
	return temp;
}
Personal tools
Namespaces
Variants
Actions
Navigation
Browse
Toolbox