c语言如何封装函数接口 c++怎么封装函数

C语言中如何将自己常用的函数封装到编译器的库函数中具体应该怎么做呢?用编译器提供c语言如何封装函数接口的库管理工具 。
C语言c语言如何封装函数接口的编译器都会提供一个命令行工具c语言如何封装函数接口,可以把自己编译后的.obj模块加入指定的库文件,以后使用时只需要连接该库文件即可 。这个命令行工具通常是lib.exe,用这个工具可以查看库中的模块,可以把模块加入到库中 , 可以从库中删除模块 。这个工具不仅仅是自己建立的库文件的管理工具,可以管理所有的库文件,包括C语言提供的标准库 。
C语言怎么封装自己写的函数用C语言的时候,您是否还在使用printf函数来输出日志呢?您是否考虑过将printf函数打印的内容存到文件中去呢?您是否想拥有一个可选择的既支持输出到屏幕又支持存储到文件中的日志函数呢?很高兴的告诉您,如果您愿意的话 , 欢迎使用本人编写的一个一套日志函数 , 该套函数由五部分组成,分别是宏变量BUF_SIZE、结构体log_st、log_init函数、log_debug函数和log_checksize函数 。其中宏变量BUF_SIZE用来限制每次输出的日志的最大长度;结构体用来存储用户需求,包括文件路径、文件描述符号、单个文件最大大小、输出方式标志、文件命名标志等;log_init函数用来完成用户需求录入、文件创建等功能,在mian函数的开始调用一次即可;log_debug函数的功能跟printf很类似 , 是在printf基础上进行的扩充 , 实现将日志输出到屏幕或者写入到文件,在需要打印日志的地方调用该函数;log_checksize函数用来检测日志文件大小是否超过最大大小限制 , 它需要您定时或者定点调用它,如果一直不调用,则日志文件将不受指定的最大大小限制 。
一、定义宏变量BUF_SIZE
view plaincopy to clipboardprint?
#define BUF_SIZE 1024
二、定义log_st结构体
view plaincopy to clipboardprint?
typedef struct _log_st log_st;
struct _log_st
{
char path[128];
int fd;
int size;
int level;
int num;
};
三、定义log_init函数
参数说明:path——您要存储的文件路径;size——单个文件的最大大小,如果超过该大小则新建新的文件用来存储;level——日志输出方式,建议在上层限制其值的范围为0到3,0表示日志既不输出到屏幕也不创建文件和保存到文件,1表示日志保存到文件但不输出到屏幕,2表示日志既输出到屏幕也保存到文件,3表示日志只输出到文件而不创建文件和存入文件;num——日志文件命名方式,非0表示以(int)time(NULL)作为文件名来保存文件,文件数量随着日志量的递增而递增;0表示以“.new”和“.bak”为文件名来保存文件,文件数量不超过两个,随着日志量的递增,旧的日志文件将被新的覆盖,更直观的说就是说.new”和“.bak”文件只保存最近的日志 。
view plaincopy to clipboardprint?
log_st *log_init(char *path, int size, int level, int num)
{
char new_path[128] = {0};
if (NULL == path || 0 == level) return NULL;
log_st *log = (log_st *)malloc(sizeof(log_st));
memset(log, 0, sizeof(log_st));
if (level != 3)
{
//the num use to control file naming
log-num = num;
if(num)
snprintf(new_path, 128, "%s%d", path, (int)time(NULL));
else
snprintf(new_path, 128, "%s.new", path);
if(-1 == (log-fd = open(new_path, O_RDWR|O_APPEND|O_CREAT|O_SYNC, S_IRUSR|S_IWUSR|S_IROTH)))
{
free(log);
log = NULL;
return NULL;
}
}
strncpy(log-path, path, 128);
log-size = (size0 ? size:0);
log-level = (level0 ? level:0);
return log;
}
四、定义log_debug函数
view plaincopy to clipboardprint?
void log_debug(log_st *log, const char *msg, ...)
{
va_list ap;
time_t now;
char *pos;
char _n = '\n';
char message[BUF_SIZE] = {0};
int nMessageLen = 0;
int sz;
if(NULL == log || 0 == log-level) return;
now = time(NULL);
pos = ctime(now);
sz = strlen(pos);
pos[sz-1]=']';
snprintf(message, BUF_SIZE, "[%s ", pos);
for (pos = message; *pos; pos);
sz = pos - message;
va_start(ap, msg);
nMessageLen = vsnprintf(pos, BUF_SIZE - sz, msg, ap);
va_end(ap);
if (nMessageLen = 0) return;
if (3 == log-level)
{
printf("%s\n", message);
return;
}
if (2 == log-level)
printf("%s\n", message);
write(log-fd, message, strlen(message));
write(log-fd, _n, 1);
fsync(log-fd);
}
五、定义log_checksize函数
view plaincopy to clipboardprint?
void log_checksize(log_st *log)
{
【c语言如何封装函数接口 c 怎么封装函数】struct stat stat_buf;
char new_path[128] = {0};
char bak_path[128] = {0};
if(NULL == log || 3 == log-level || '\0' == log-path[0]) return;
memset(stat_buf, 0, sizeof(struct stat));
fstat(log-fd, stat_buf);
if(stat_buf.st_sizelog-size)
{
close(log-fd);
if(log-num)
snprintf(new_path, 128, "%s%d", log-path, (int)time(NULL));
else
{
snprintf(bak_path, 128, "%s.bak", log-path);
snprintf(new_path, 128, "%s.new", log-path);
remove(bak_path); //delete the file *.bak first
rename(new_path, bak_path); //change the name of the file *.new to *.bak
}
//create a new file
log-fd = open(new_path, O_RDWR|O_APPEND|O_CREAT|O_SYNC, S_IRUSR|S_IWUSR|S_IROTH);
}
}
C库如何封装成C接口C一般不能直接调用C函数库 , 需要将C库封装成C接口后,才可以使用C调用 。
下面举例,说明一个封装策略:
//code in add.cxx
#include "add.h"
int sample::method()
{
cout"method is called!\n";
}
//code in add.h
#include
using namespace std;
class sample
{
public:
int method();
};
将上面的两个文件生成动态库libadd.so放到 /usr/lib目录下,编译命令如下:
sudo g-fpic -shared -g -o /usr/lib/libadd.so add.cxx -I ./
由于在C中不能识别类,所以要将上面类的成员函数,要封装成C接口函数才能被调用 。下面进行封装,将输出接口转换成C接口 。
//code in mylib.cxx
#include "add.h"
#ifndef _cplusplus
#define _cplusplus
#include "mylib.h"
#endif
int myfunc()
{
sample ss;
ss.method();
return 0;
}
//code in mylib.h
#ifdef _cplusplus
extern "C"
{
#endif
int myfunc();
#ifdef _cplusplus
}
#endif
在linux下 , gcc编译器并没用变量_cplusplus来区分是C代码还是C代码(没有宏定义),如果使用gcc编译器,这里我们可以自己定义一个变量_cplusplus用于区分C和C代码,所以在mylib.cxx中定义 了一个变量_cplusplus用于识别是否需要“extern "C"”将函数接口封装成C接口 。但是如果使用g编译器则不需要专门定义_cplusplus , 编译命令如下:
g-fpic -shared -g -o mylib.so mylib.cxx -la -I ./
main.c
#include
#include
#include "mylib.h"
int
main()
{
int (*dlfunc)();
void *handle; //定义一个句柄
handle = dlopen("./mylib.so", RTLD_LAZY);//获得库句柄
dlfunc = dlsym(handle, "myfunc"); //获得函数入口
(*dlfunc)();
dlclose(handle);
return 0;
}
编译命令如下:
gcc -o main main.c ./mylib.so -ldl
下面就可以执行了 。
需要说明的是,由于main.c 和 mylib.cxx都需要包含mylib.h,并且要将函数myfunc封装成C接口函数输出需要“extern "C"”,而C又不识别“extern "C"” , 所以需要定义_cplusplus来区别处理mylib.h中的函数myfunc 。
在main.c的main函数中直接调用myfunc()函数也能执行,这里介绍的是常规调用库函数的方法 。
C语言 把以下函数封装成自己写的函数和接口 strlen atoi strcpy strcat s楼上智商拙计啊
int
my_strlen(char
*buf)
{
int
count
=
0;
for(;
*buf
!=
'\0';
*buf
)
{
count
;
}
return
count;
}
剩下的继续追问吧,一次上传不完
c语言如何实现函数的调用如何调用C语言写的库,如a.lib等c语言如何封装函数接口,有对应的库头文件a.h 。假设a.h中定义c语言如何封装函数接口了函数:
int
WhyCoding(int
a,
float
b);
做法是,
/*
cpp_a.h
*/
extern
"C"
{
#include
"a.h"
}

/*
cpp_a.h
*/
extern
"C"
{
int
WhyCoding(int
a,
float
b);
/*
重定义所有的C函数
*/
}
从上面可以看出 , extern
"C"
是用在C和C之间的桥梁 。之所以需要这个桥梁是因为C编译器编译函数时不带
函数的类型信息,只包含函数符号名字,如C编译器把函数int
a(float
x)编译成类似_a这样的符号,C连接器只要
找到了调用函数的符号,就可以连接成功,它假设参数类型信息是正确的,这是C编译连接器的缺点 。而C
编译器为了实现函数重载,编译时会带上函数的类型信息,如c语言如何封装函数接口他把上面的a函数可能编译成_a_float这样的
符号为了实现重载,注意它还是没有带返回值得信息,这也是为什么C不支持采用函数返回值来区别函数
重载的原因之一,当然,函数的使用者对函数返回值的处理方式(如忽略)也是重要原因 。
基于以上,C调用C,首先需要用封装函数把对C的类等的调用封装成C函数以便C调用,于是extern
"C"

作用是:让编译器知道这件事,然后以C语言的方式编译和连接封装函数.(通常是把封装函数用C编译器按C
方式编译,用了extern
"C"
后,编译器便依C的方式编译封装接口 , 当然接口函数里面的C语法还是按C方式
编译;对于C语言部分--调用者,还是按C语言编译;分别对C接口部分和C部分编译后,再连接就可以实现C
调用C了).
相反,C调用C函数,extern
"C"
的作用是:让C连接器找调用函数的符号时采用C的方式,即使用_a而不是
_a_float来找调用函数 。
c语言如何封装函数接口的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于c怎么封装函数、c语言如何封装函数接口的信息别忘了在本站进行查找喔 。

    推荐阅读