Languages/C/SplitCH
(Difference between revisions)
(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) |
||
Line 3: | Line 3: | ||
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. | + | * (1) The header MUST contain what is necessary from the '''outside''' of the source file. |
− | * The header SHOULD NOT contain, what is not necessary. | + | * (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 simpler. | ||
− | * The header file MUST prevent multiple inclusion | + | * (3) The header file MUST prevent multiple inclusion |
− | * A header file SHOULD be complete (it defines or includes all it needs). | + | * (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> | ** Example, if you use a uint32_t parameter in a function, the header should include <stdint.h> | ||
− | * A header file SHOULD not include files only used in source file | + | * (5) A header file SHOULD not include files only used in source file |
− | * The header SHOULD be commented enough so there is no need to open the source file. | + | * (6) The header SHOULD be commented enough so there is no need to open the source file. |
− | * The source file MUST include the header | + | * (7) The source file MUST include the header, preferably first |
− | ** This will ensure | + | ** This will ensure consistency |
+ | * (8) All symbols not exported by the header | ||
+ | ** Do not pollute the linker namespace | ||
== Temperature sensor example == | == Temperature sensor example == | ||
Here is a simple main : | Here is a simple main : | ||
− | |||
− | |||
<source lang='c'> | <source lang='c'> | ||
#include <stdio.h> | #include <stdio.h> | ||
− | # | + | #include "temp_sensor.h" |
+ | |||
+ | int main(int argc, char *argv[]) | ||
+ | { | ||
+ | return printf("temperature is : %d", temp_sensor_get()); | ||
+ | } | ||
+ | |||
+ | </source> | ||
+ | <source lang='c'> | ||
+ | #ifndef TEMP_SENSOR_H // (3) prevent multiple inclusion, see the #endif at the end | ||
+ | #define TEMP_SENSOR_H | ||
+ | |||
+ | #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. | ||
+ | * | ||
+ | * \waring the value will be 0 if the sensor read fails. | ||
+ | */ | ||
+ | uint16_t temp_sensor_get(void); | ||
+ | |||
+ | #endif /* TEMP_SENSOR_H */ | ||
+ | </source> | ||
+ | <source lang='c'> | ||
+ | #include "temp_sensor.h" // (7) Include the header for compile-time checks | ||
+ | #include <super_os/i2c.h> // (2) The i2c bus is not used in main | ||
+ | |||
+ | // (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(SENSOR_ADDRESS, SENSOR_REG, value, 2) != 0) | ||
+ | { | ||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | return 1; | ||
+ | } | ||
+ | |||
+ | // (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) | ||
+ | { | ||
+ | temp = 0; | ||
+ | } | ||
+ | |||
+ | return temp; | ||
+ | } | ||
</source> | </source> | ||
− |
Revision as of 14:41, 10 December 2013
|
Source and header file split
It is sometimes complicated to split the header and the source file, here are some hints:
- (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 simpler.
- (3) The header file MUST prevent multiple inclusion
- (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>
- (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.
- (7) The source file MUST include the header, preferably first
- This will ensure consistency
- (8) All symbols not exported by the header
- Do not pollute the linker namespace
Temperature sensor example
Here is a simple main :
#include <stdio.h> #include "temp_sensor.h" int main(int argc, char *argv[]) { return printf("temperature is : %d", temp_sensor_get()); }
#ifndef TEMP_SENSOR_H // (3) prevent multiple inclusion, see the #endif at the end #define TEMP_SENSOR_H #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. * * \waring the value will be 0 if the sensor read fails. */ uint16_t temp_sensor_get(void); #endif /* TEMP_SENSOR_H */
#include "temp_sensor.h" // (7) Include the header for compile-time checks #include <super_os/i2c.h> // (2) The i2c bus is not used in main // (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(SENSOR_ADDRESS, SENSOR_REG, value, 2) != 0) { return 0; } return 1; } // (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) { temp = 0; } return temp; }