C一般不能直接調(diào)用C++函數(shù)庫(kù),需要將C++庫(kù)封裝成C接口后,才可以使用C調(diào)用。
成都創(chuàng)新互聯(lián)是專(zhuān)業(yè)的田家庵網(wǎng)站建設(shè)公司,田家庵接單;提供網(wǎng)站建設(shè)、成都網(wǎng)站制作,網(wǎng)頁(yè)設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專(zhuān)業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行田家庵網(wǎng)站開(kāi)發(fā)網(wǎng)頁(yè)制作和功能擴(kuò)展;專(zhuān)業(yè)做搜索引擎喜愛(ài)的網(wǎng)站,專(zhuān)業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來(lái)合作!
下面舉例,說(shuō)明一個(gè)封裝策略:
//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();
};
將上面的兩個(gè)文件生成動(dòng)態(tài)庫(kù)libadd.so放到 /usr/lib目錄下,編譯命令如下:
sudo g++ -fpic -shared -g -o /usr/lib/libadd.so add.cxx -I ./
由于在C中不能識(shí)別類(lèi),所以要將上面類(lèi)的成員函數(shù),要封裝成C接口函數(shù)才能被調(diào)用。下面進(jìn)行封裝,將輸出接口轉(zhuǎn)換成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編譯器并沒(méi)用變量_cplusplus來(lái)區(qū)分是C代碼還是C++ 代碼(沒(méi)有宏定義),如果使用gcc編譯器,這里我們可以自己定義一個(gè)變量_cplusplus用于區(qū)分C和C++代碼,所以在mylib.cxx中定義 了一個(gè)變量_cplusplus用于識(shí)別是否需要“extern "C"”將函數(shù)接口封裝成C接口。但是如果使用g++編譯器則不需要專(zhuān)門(mén)定義_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; //定義一個(gè)句柄
handle = dlopen("./mylib.so", RTLD_LAZY);//獲得庫(kù)句柄
dlfunc = dlsym(handle, "myfunc"); //獲得函數(shù)入口
(*dlfunc)();
dlclose(handle);
return 0;
}
編譯命令如下:
gcc -o main main.c ./mylib.so -ldl
下面就可以執(zhí)行了。
需要說(shuō)明的是,由于main.c 和 mylib.cxx都需要包含mylib.h,并且要將函數(shù)myfunc封裝成C接口函數(shù)輸出需要“extern "C"”,而C又不識(shí)別“extern "C"”,所以需要定義_cplusplus來(lái)區(qū)別處理mylib.h中的函數(shù)myfunc。
在main.c的main函數(shù)中直接調(diào)用myfunc()函數(shù)也能執(zhí)行,這里介紹的是常規(guī)調(diào)用庫(kù)函數(shù)的方法。
用編譯器提供的庫(kù)管理工具。
C語(yǔ)言的編譯器都會(huì)提供一個(gè)命令行工具,可以把自己編譯后的.obj模塊加入指定的庫(kù)文件,以后使用時(shí)只需要連接該庫(kù)文件即可。這個(gè)命令行工具通常是lib.exe,用這個(gè)工具可以查看庫(kù)中的模塊,可以把模塊加入到庫(kù)中,可以從庫(kù)中刪除模塊。這個(gè)工具不僅僅是自己建立的庫(kù)文件的管理工具,可以管理所有的庫(kù)文件,包括C語(yǔ)言提供的標(biāo)準(zhǔn)庫(kù)。
用C語(yǔ)言的時(shí)候,您是否還在使用printf函數(shù)來(lái)輸出日志呢?您是否考慮過(guò)將printf函數(shù)打印的內(nèi)容存到文件中去呢?您是否想擁有一個(gè)可選擇的既支持輸出到屏幕又支持存儲(chǔ)到文件中的日志函數(shù)呢?很高興的告訴您,如果您愿意的話,歡迎使用本人編寫(xiě)的一個(gè)一套日志函數(shù),該套函數(shù)由五部分組成,分別是宏變量BUF_SIZE、結(jié)構(gòu)體log_st、log_init函數(shù)、log_debug函數(shù)和log_checksize函數(shù)。其中宏變量BUF_SIZE用來(lái)限制每次輸出的日志的最大長(zhǎng)度;結(jié)構(gòu)體用來(lái)存儲(chǔ)用戶需求,包括文件路徑、文件描述符號(hào)、單個(gè)文件最大大小、輸出方式標(biāo)志、文件命名標(biāo)志等;log_init函數(shù)用來(lái)完成用戶需求錄入、文件創(chuàng)建等功能,在mian函數(shù)的開(kāi)始調(diào)用一次即可;log_debug函數(shù)的功能跟printf很類(lèi)似,是在printf基礎(chǔ)上進(jìn)行的擴(kuò)充,實(shí)現(xiàn)將日志輸出到屏幕或者寫(xiě)入到文件,在需要打印日志的地方調(diào)用該函數(shù);log_checksize函數(shù)用來(lái)檢測(cè)日志文件大小是否超過(guò)最大大小限制,它需要您定時(shí)或者定點(diǎn)調(diào)用它,如果一直不調(diào)用,則日志文件將不受指定的最大大小限制。
一、定義宏變量BUF_SIZE
view plaincopy to clipboardprint?
#define?BUF_SIZE?1024
二、定義log_st結(jié)構(gòu)體
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函數(shù)
參數(shù)說(shuō)明:path——您要存儲(chǔ)的文件路徑;size——單個(gè)文件的最大大小,如果超過(guò)該大小則新建新的文件用來(lái)存儲(chǔ);level——日志輸出方式,建議在上層限制其值的范圍為0到3,0表示日志既不輸出到屏幕也不創(chuàng)建文件和保存到文件,1表示日志保存到文件但不輸出到屏幕,2表示日志既輸出到屏幕也保存到文件,3表示日志只輸出到文件而不創(chuàng)建文件和存入文件;num——日志文件命名方式,非0表示以(int)time(NULL)作為文件名來(lái)保存文件,文件數(shù)量隨著日志量的遞增而遞增;0表示以“.new”和“.bak”為文件名來(lái)保存文件,文件數(shù)量不超過(guò)兩個(gè),隨著日志量的遞增,舊的日志文件將被新的覆蓋,更直觀的說(shuō)就是說(shuō).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?=?(size??0???size:0);
log-level?=?(level??0???level:0);
return?log;
}
四、定義log_debug函數(shù)
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函數(shù)
view plaincopy to clipboardprint?
void?log_checksize(log_st?*log)
{
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_size??log-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);
}
}
您好,對(duì)于你的遇到的問(wèn)題,我很高興能為你提供幫助,我之前也遇到過(guò)喲,以下是我的個(gè)人看法,希望能幫助到你,若有錯(cuò)誤,還望見(jiàn)諒!。展開(kāi)全部
用C語(yǔ)言的時(shí)候,您是否還在使用printf函數(shù)來(lái)輸出日志呢?您是否考慮過(guò)將printf函數(shù)打印的內(nèi)容存到文件中去呢?您是否想擁有一個(gè)可選擇的既支持輸出到屏幕又支持存儲(chǔ)到文件中的日志函數(shù)呢?很高興的告訴您,如果您愿意的話,歡迎使
一、定義宏變量BUF_SIZE
view plaincopy to clipboardprint?
#define BUF_SIZE 1024
二、定義log_st結(jié)構(gòu)體
view plaincopy to clipboardprint?
typedef struct _log_st log_st;
struct _log_st
{
char path[128];
int fd;
int size; 非常感謝您的耐心觀看,如有幫助請(qǐng)采納,祝生活愉快!謝謝!