问题
我入职了嵌入式软件工程师,看到公司的项目代码是用C语言以面向对象的思维编码的,我觉得这很好,很想学习。因此,在这里询问我该如何学习,应该去看哪些资料?顺便也想问问嵌入式中用C语言以面向对象的思维编码是否合适,在什么情况下建议使用?
以下代码是我看过公司代码后,自己尝试进行了思考,也尝试简单用C语言以面向对象的思维实现一个单例模式。
代码
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "cmsis_armcc.h"
/* ------------------------------------------------------------------------------------------------------------------ */
/**
* 标记宏定义,用于修饰函数、变量、常量、结构体成员等等。部分宏标记具有关键字修饰功能,注意使用。
*
*/
// 公共可读写(外部可访问,可修改)
#define PUBLIC __attribute__((annotate("public")))
// 公共只读(外部可访问,不可修改)
#define PUBLIC_CONST __attribute__((annotate("public const")))
// 内部使用(外部禁止访问),主要用于标记结构体成员,不可被外部修改与访问
#define INTERNAL __attribute__((annotate("internal")))
// 文件静态私有(真正的私有)
#define PRIVATE_STATIC static __attribute__((annotate("private static")))
// 内部内联函数,用于 .c 文件中定义的函数
#define PRIVATE_INLINE __STATIC_INLINE __attribute__((annotate("private inline")))
// 公共内联函数,用于在头文件中定义的函数
#define PUBLIC_INLINE __STATIC_INLINE __attribute__((annotate("public inline")))
/* ---------------------------------------------------- 内存分配公共接口 ---------------------------------------------------- */
/**
* @brief 内存分配类型
*
*/
typedef enum alloc_type
{
ALLOC_STATIC = 0, // 静态内存分配
ALLOC_DYNAMIC, // 动态内存分配
}alloc_type_t;
/**
* @brief 内存分配结果类型
*
*/
typedef enum alloc_result_type
{
ALLOC_RESULT_SUCCESS = 0, // 成功
ALLOC_RESULT_OUT_PTR_INVALID, // 输出指针无效
ALLOC_RESULT_STATIC_BUFFER_NULL, // 静态内存分配失败
ALLOC_RESULT_DYNAMIC_BUFFER_NULL, // 动态内存分配失败
ALLOC_ALLOC_TYPE_INVALID, // 内存分配类型无效
ALLOC_RESULT_FREE_PTR_INVALID, // 释放指针无效
}alloc_result_type_t;
/**
* @brief 内存分配
*
* @param alloc_type 内存分配类型
* @param out_ptr 输出指针
* @param byte_size 动态内存大小,仅在动态内存分配时有效,其他情况为0
* @param static_buffer 静态内存缓冲区
* @return alloc_result_type_t 内存分配结果类型
*/
PUBLIC alloc_result_type_t memory_alloc(alloc_type_t alloc_type, void **out_ptr, size_t byte_size, void *static_buffer)
{
if (out_ptr == NULL)
{
return ALLOC_RESULT_OUT_PTR_INVALID;
}
*out_ptr = NULL;
switch (alloc_type)
{
case ALLOC_STATIC:
if (static_buffer == NULL)
{
*out_ptr = NULL;
return ALLOC_RESULT_STATIC_BUFFER_NULL;
}
*out_ptr = static_buffer;
break;
case ALLOC_DYNAMIC:
*out_ptr = malloc(byte_size);
if (*out_ptr == NULL)
{
return ALLOC_RESULT_DYNAMIC_BUFFER_NULL;
}
break;
default:
return ALLOC_ALLOC_TYPE_INVALID;
}
return ALLOC_RESULT_SUCCESS;
}
/**
* @brief 内存释放
*
* @param alloc_type 内存分配类型
* @param ptr 内存指针
* @return alloc_result_type_t 内存释放结果类型
*/
PUBLIC alloc_result_type_t memory_free(alloc_type_t alloc_type, void **ptr)
{
if (ptr == NULL || *ptr == NULL)
{
return ALLOC_RESULT_FREE_PTR_INVALID;
}
switch (alloc_type)
{
case ALLOC_STATIC:
*ptr = NULL;
break;
case ALLOC_DYNAMIC:
free(*ptr);
*ptr = NULL;
break;
default:
return ALLOC_ALLOC_TYPE_INVALID;
}
return ALLOC_RESULT_SUCCESS;
}
/* ------------------------------------------------------ 接口结构体 ----------------------------------------------------- */
// 数据操作接口
typedef struct intface_data_operation
{
bool (*write)(void *self, uint8_t *in_data, uint16_t len);
bool (*send)(void *self);
bool (*receive)(void *self);
}intface_data_operation_t;
/**
* @brief 清理数据操作接口,将所有成员变量设置为0值
*
* @param ptr 数据操作接口指针
* @return None
*/
PUBLIC_INLINE void intface_data_clean(intface_data_operation_t *ptr)
{
if (ptr == NULL)
{
return;
}
memset(ptr, 0, sizeof(intface_data_operation_t));
}
/* ----------------------------------------------------- 对象相关定义 ----------------------------------------------------- */
typedef struct Data
{
PUBLIC_CONST uint8_t *pubc_data; // 数据缓冲区指针
PUBLIC_CONST uint16_t pubc_len; // 数据缓冲区大小
PUBLIC intface_data_operation_t publ_operation; // 数据操作接口
}Data_t;
#define STATIC_ALLOC
#define DATA_BUFF_SIZE 128
#ifdef STATIC_ALLOC
PRIVATE_STATIC Data_t s_data;
PRIVATE_STATIC uint8_t s_buffer[DATA_BUFF_SIZE];
#endif
PRIVATE_STATIC Data_t *s_ptr_data = NULL;
PRIVATE_STATIC bool write_data(void *self, uint8_t *data, uint16_t len)
{
if (!self || !data || len == 0 || len > DATA_BUFF_SIZE) return false;
Data_t *ptr_data = (Data_t *)self;
memcpy(ptr_data->pubc_data, data, len);
ptr_data->pubc_len += len;
printf("write_data: %*s\n", len, data);
return true;
}
PRIVATE_STATIC bool send_data(void *self)
{
if (!self) return false;
Data_t *ptr_data = (Data_t *)self;
printf("send_data: %*s\n", ptr_data->pubc_len, ptr_data->pubc_data);
return true;
}
PRIVATE_STATIC bool receive_data(void *self)
{
if (!self) return false;
Data_t *ptr_data = (Data_t *)self;
memcpy(ptr_data->pubc_data, "hello world", 11);
ptr_data->pubc_len = 11;
printf("receive_data: %*s\n", ptr_data->pubc_len, ptr_data->pubc_data);
return true;
}
/**
* @brief 获取数据对象实例,单例模式实现
*
* @return Data_t* 数据对象实例指针
*/
PUBLIC Data_t *data_get_instance(void)
{
if (s_ptr_data) return s_ptr_data;
#ifdef STATIC_ALLOC
memory_alloc(ALLOC_STATIC, &s_ptr_data, 0, &s_data);
memory_alloc(ALLOC_STATIC, &s_ptr_data->pubc_data, 0, s_buffer);
#else
memory_alloc(ALLOC_DYNAMIC, &ptr_data, sizeof(Data_t), NULL);
memory_alloc(ALLOC_DYNAMIC, &ptr_data->pubc_data, DATA_BUFF_SIZE, NULL);
#endif
s_ptr_data->pubc_len = 0;
// intface_data_clean(&s_ptr_data->publ_operation);
s_ptr_data->publ_operation.write = write_data;
s_ptr_data->publ_operation.send = send_data;
s_ptr_data->publ_operation.receive = receive_data;
return s_ptr_data;
}
PUBLIC void data_clean_instance(Data_t **ptr_data)
{
if (!ptr_data || (!*ptr_data)) return;
#ifdef STATIC_ALLOC
memory_free(ALLOC_STATIC, &s_ptr_data->pubc_data);
memory_free(ALLOC_STATIC, &s_ptr_data);
#else
memory_free(ALLOC_DYNAMIC, &s_ptr_data->pubc_data);
memory_free(ALLOC_DYNAMIC, &s_ptr_data);
#endif
*ptr_data = NULL;
}
int main(void)
{
Data_t *ptr_data = data_get_instance();
ptr_data->publ_operation.write(ptr_data, "hello world xxx", 16);
ptr_data->publ_operation.send(ptr_data);
ptr_data->publ_operation.receive(ptr_data);
data_clean_instance(&ptr_data);
while (1)
{
}
// return 0;
}