面向对象的C语言

2020-12-21 16:17:35 浏览数 (1)

大家在学C、C 的时候,老师多半会讲过:C语言是面向过程的编程语言,C 是面向对象的编程语言。但归根结底,面向过程还是面向对象,这是编程思想的差异,而不是语言的差异。笔者最近在看baresip源码,C语言也能写成面向对象。

笔者,想了个应用场景,写了个简单的demo。笔者当年的第一份工作,维护BPLA(北洋打印机指令集)SDK,其中重要的一项工作是,通过串口、并口、usb、网络等软硬件接口,发送控制指令。

笔者先创建了一个interface.h文件,相当于C 里的虚类。

代码语言:javascript复制

typedef void (* p_func_connect) ();
typedef void (* p_func_send_cmd) (char *);
typedef void (* p_func_disconnect) ();

struct interface
{    
    char *name;
   p_func_connect connect;
   p_func_disconnect disconnect;
   p_func_send_cmd send_cmd;
};

然后创建modules文件,并在此文件夹下,创建了usb.ccom.cdriver.cnetwork.c,分别对应USB、串口、驱动接口、网络接口的实现。相当于C 中,继承虚类的各个子类实现。usb.c如下:

代码语言:javascript复制

#include "../interface.h"
static void connect() {
    printf("connect by usbn");
}

static void disconnect() {
    printf("disconnect by usbn");
}

static void send_cmd(char *cmd) {
    printf("send cmd by usb: %sn", cmd);
}

const struct interface usb = {    "usb",
   connect,
   disconnect,
   send_cmd
};

为了让这些“类”用起来更优雅些,笔者在interface.hinterface.c中添加了find_device函数,添加了static.c

interface.c文件

代码语言:javascript复制

#include "interface.h"

extern const struct interface *interfaces[];

const struct interface * find_device(char *name) {
    int i = 0;    
    struct interface *dev = interfaces[0];    
    
    for (; dev; i  ) {
        if (0 == strcmp(name, dev->name)) {
            break;
       }       dev = interfaces[i   1];
            
   }
    
     return dev;
}
     

static.c

代码语言:javascript复制

#include <stdio.h>
#include "interface.h"

extern const struct interface com;
extern const struct interface usb;
extern const struct interface driver;
extern const struct interface network;

const struct interface *interfaces[] = {
   &com,
   &usb,
   &driver,
   &network,
   NULL };

static.c进阶版,Makefile文件动态生成:

代码语言:javascript复制

MODULES:=$(wildcard ./modules/*.c)
MODULES:=$(patsubst ./modules/%.c, %, $(MODULES))static.c:
   echo "#include <stdio.h>" > $@
   echo "#include "interface.h"n" >> $@    
    for n in $(MODULES); do 
       echo "extern const struct interface $${n};"  >> $@  ; 
   done
   echo "" >> $@
   echo "const struct interface *interfaces[] = {" >> $@    
    for n in $(MODULES); do 
       echo "  &$${n},"  >> $@  ; 
   done
   echo "  NULL };" >> $@

也可根据实际情况,动态设置使用哪些module,如,现在使用的打印机只有usb口和网口。

代码语言:javascript复制

MODULES:=usb network

最后贴下main.c文件和调用

代码语言:javascript复制

#include <stdio.h>
#include <stdlib.h>
#include "interface.h"

int main() {
    struct interface *dev = NULL;    
    char name[255];    
    
    while (1) {
        memset(name, 0, 255);
       gets(name);       dev = find_device(name);        
        if (dev) {
           dev->connect();
           dev->send_cmd("print hello world");
           dev->disconnect();
       } else {          
            printf("no such device: %s!n", name);
       }
   }    
             
     return 0;
}
     

运行如下:

代码语言:javascript复制

➜  communication ./main
warning: this program uses gets(), which is unsafe.
usb
connect by usb
send cmd by usb: print hello world
disconnect by usb
network
connect by network
send cmd by network: print hello world
disconnect by network

附:

Makefile文件:

代码语言:javascript复制

MODULES:=$(wildcard ./modules/*.c)
MODULES:=$(patsubst ./modules/%.c, %, $(MODULES))

SRC:=$(wildcard *.c)
SRC =$(patsubst %, modules/%.c, $(MODULES))

OBJ:=$(patsubst %.c, %.o, $(SRC))
CC:=gcc -fPIC

all: static.c $(OBJ)
   $(CC) $(OBJ) -o mainstatic.c:
   echo "#include <stdio.h>" > $@
   echo "#include "interface.h"n" >> $@    
    for n in $(MODULES); do 
       echo "extern const struct interface $${n};"  >> $@  ; 
   done
   echo "" >> $@
   echo "const struct interface *interfaces[] = {" >> $@   
    for n in $(MODULES); do 
       echo "  &$${n},"  >> $@  ; 
   done
   echo "  NULL };" >> $@%o:%c
   $(CC) $(CFLAGS) -c $< -o $@

clean:
   rm *.o
   rm ./modules/*.o
   rm main
   rm static.c
    

0 人点赞