# C 也可以寫的很OOP 簡單範例與簡易Makefile
###### tags: `C LANGUAGE` `oop` `Object-oriented programming` `C99` `ring buffer`
<style>
.blue {
color: blue;
}
.bgblue {
color: blue;
font-size: 24px;
font-weight: bold;
}
.red {
color: red;
font-size: 24px;
font-weight: bold;
}
.bgred {
color: red;
font-size: 28px;
font-weight: bold;
}
h1 {text-align: center;}
h2 {text-align: center;}
</style>
Author: CrazyMonkey
email: kccddb@gmail.com
Date: 20230214
Copyright: CC BY-NC-SA

1. 了解這例子可以更深刻了解
物件導向程式設計(OOP :Object-oriented programming) , 例如 java, javascript, ...等
2. 了解 **this** 的意義, 這裡也用到 **function pointer**
3. object 的生成(constructor)與回收(deconstructor)需要付出 garbage collection 的代價, 如果於迴圈中大量使用將可能大量消耗記憶體與CPU資源.
```c=
//crect.c
/*
*
*Copyright (C) 2019 My-Company-Name
*Version: 1.101 2019/01/01
*Authors: WhoAmI, <whomani@xxxgmail.com>
*Complie and Link:
* gcc -Wall -c crect.c -o crect.o
*
*TODO: Homework, DUE DATE: 2019/01/01
*
*BUGS:
*/
#include <stdlib.h>
#include "crect.h"
static void SetParameter(CRectangle *rect,int a, int b)
{
//"this" pointer
rect->width=a;
rect->height=b;
}
static int GetArea(CRectangle *rect)
{
return (rect->width)* (rect->height);
}
//global functions
//constructor
CRectangle *init_CRectangle(int width,int height)
{
CRectangle *pThis ;
//allocte object storage
pThis=(CRectangle *)malloc(sizeof(CRectangle));
if(pThis){
//assign function pointers and properties
pThis->set_parameters = SetParameter;
pThis->area=GetArea;
pThis->width=width;
pThis->height=height;
}
return pThis;
}
//deconstructor
int exit_CRectangle(CRectangle *pThis){
if(pThis){
free(pThis); //release object
return 0;
}
return -1;
}
//crect.h
typedef struct Rectangle{
int width, height;
int (*area) (struct Rectangle *);
void (*set_parameters )( struct Rectangle *,int,int);
}CRectangle;
CRectangle *init_CRectangle(int width,int height);
int exit_CRectangle(CRectangle *pThis);
/* app.c
demo
gcc app.c crect.c -o app
*/
#include <stdio.h>
#include "crect.h"
int main () {
CRectangle *rect;
//init object
rect=init_CRectangle(5,3); //allocate memory and initialize object
if(!rect){
printf("Cannot init CRectangle\n");
}
rect->set_parameters (rect,2,4);
printf("area:%d\n", rect->area(rect));
//exit
exit_CRectangle(rect); //release object
return 0;
}
```
**HW.** 設計一 CPolygon (多邊形)
CPolygon *init_CPolygon(int edges,...);
//計算周長
int (*Perimeter) (struct Polygon *);
int exit_CRectangle(CPolygon *pThis);
Hint:
[stdarg, va_start, va_arg, va_end, va_copy - variable argument lists](https://linux.die.net/man/3/va_start)
<h2>
簡易的 Makefile
</h2>
注意1. 是 <tab> 鍵不是空白 2.必須存為unix 檔案格式
當您改變 CC, CFLAGS, LDFLAGS, ...等可以改變為不同 CPU, 如此以後才方便移植至其他 SoC!
```c=
CC = gcc
AR = ar
RANLIB = ranlib
STRIP = strip
CFLAGS = -Wall -DDEBUG0
LDFLAGS= -lpthread
CSOURCE= crect.c app.c
all: homework2
homework2: ${CSOURCE}
${CC} ${CSOURCE} ${CFLAGS} -o app
${STRIP} app
clean:
rm app
```
---
[ar - create, modify, and extract from archives](https://linux.die.net/man/1/ar)
[ranlib - generate an index to an archive ](https://www.man7.org/linux/man-pages/man1/ranlib.1.html)
[使用 gcc 自製 C/C++ 靜態、共享與動態載入函式庫教學, by G. T. Wang](https://blog.gtwang.org/programming/howto-create-library-using-gcc/)
:::info
Futher Reading:
-fPIC, PIC = [position independent code](https://en.wikipedia.org/wiki/Position-independent_code)
Ref.
[Creating a shared and static library with the gnu compiler (gcc), by Alberto Fanjul (albfan).](https://renenyffenegger.ch/notes/development/languages/C-C-plus-plus/GCC/create-libraries/index)
:::
---
<h2>C99,
Linux kernel 大都使用此寫法</h2>
```c=
#include <stdio.h>
#include <stdlib.h>
/*
C99
gcc xxx -std=c99
*/
typedef struct student{
int id;
int (*year)(struct student * );
int score;
} Student;
static int year (struct student *pthis){
return pthis->id;
}
int main(int argc, char *argv[]){
Student s= (Student) {.id=10,.year=year,};
printf("year=%d\n",s.year(&s));
}
```
drivers/char/misc.c
```c=
static struct file_operations misc_proc_fops = {
.owner = THIS_MODULE,
.open = misc_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
};
```
<h2>
ring buffer
</h2>
簡單但實用的 [ring buffer (circular buffer, circular queue and cyclic buffer) ](https://en.wikipedia.org/wiki/Circular_buffer), 請自行測試
尤其是記憶體受限時, 例如 單晶片, embedded system 或資料變動快速與大量時(使用ring buffer (fixed maximum size) 不需要 經常 malloc, free, 如此可減少 OS 進行 garbage collection! )
有次 研發人員 處理 快速大量資料時(每次大小不一定) 用 linked list, 改建議 他使用 ring buffer.
[Ring Buffer OOP version](https://hackmd.io/@pingulinux/CircularBuffer)
```c=
/*
*
*Copyright CC BY-NC-SA
*Version:
*Authors: WhoAmI
*Complie and Link:
*
*
*TODO:
*
*BUGS:
*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
typedef struct ring_buffer
{
void *buffer; // data buffer
void *buffer_end; // end of data buffer
size_t capacity; // maximum number of items in the buffer
size_t count; // number of items in the buffer
size_t sz; // size of each item in the buffer
void *head; // pointer to head
void *tail; // pointer to tail
} ring_buffer;
ring_buffer * ring_init( size_t capacity, size_t sz)
{
ring_buffer *ring;
ring=malloc(sizeof(ring_buffer));
if(ring==NULL)return NULL;
ring->buffer = malloc(capacity * sz);
if(ring->buffer == NULL){
free(ring);
return NULL;
}
ring->buffer_end = (unsigned char *)ring->buffer + capacity * sz;
ring->capacity = capacity;
ring->count = 0;
ring->sz = sz;
ring->head = ring->buffer;
ring->tail = ring->buffer;
}
void ring_exit(ring_buffer *ring)
{
if(ring){
free(ring->buffer);
free(ring);
}
}
int ring_push(ring_buffer *ring, const void *item)
{
if(ring->count == ring->capacity){
return 0;
}
memcpy(ring->head, item, ring->sz);
ring->head = (unsigned char*)ring->head + ring->sz;
if(ring->head == ring->buffer_end)
ring->head = ring->buffer;
ring->count++;
return ring->count;
}
int ring_pop(ring_buffer *ring, void *item)
{
if(ring->count == 0){
// handle error
return 0;
}
memcpy(item, ring->tail, ring->sz);
ring->tail = (unsigned char*)ring->tail + ring->sz;
if(ring->tail == ring->buffer_end)
ring->tail = ring->buffer;
ring->count--;
return ring->count;
}
```
:::info
[進一步研究 Document Object Model (DOM) 培養 OOP 的觀念](https://ithelp.ithome.com.tw/articles/10202689)
:::