# 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 ![](https://i.imgur.com/pGi8Ra9.jpg) 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) :::