[day07]二级指针易犯错误模型、玩转多级指针、动态库调用流程、动态库开发环境搭建、动态库核心代码编写、动态库设计和实现加日志
1.二级指针易犯错误模型
分配内存易犯模型,在主函数定义了个二级指针,然后就传给被调函数。 |
#include <stdio.h> #include <stdlib.h> void getMem(char **p) { char *tmp = *p; tmp = (char *)malloc(10 * sizeof(char)); if (tmp == NULL) { return ; } } int main(void) { /*测试1:定义二级指针置为NULL,去被调函数分配内存甩出来,这是不现实的*/ /* char **p = NULL; getMem(p); */// 注意这里p的内存地址为0,getMem里使用*p = (char *)malloc(10 * sizeof(char)); // 往*(0x00000)里面写数据是有问题的 /*测试2:就算是去*(0x00000)读值也不行的,照样崩*/ /* char **p = NULL; printf("%d\n", *p);*/ char *p = NULL; getMem(&p); // 这样才是正确的 return 0; } |
2.玩转多级指针
通过八级指针修改七级指针的值 |
#include <stdio.h> #include <stdlib.h> void modPoint(char ********p8) { *p8 = 0x8; } int main(void) { /*玩一把七级八级指针*/ /*通过八级指针修改七级指针的值*/ char *******p7 = NULL; p7 = 0x7; printf("p7:%x\n", p7); modPoint(&p7); printf("p7:%x\n", p7); return 0; } |
3.动态库调用流程
步骤:
|
lib\dll文件说明: lib是资源文件,lib描述dll中函数的引用方式。 dll存放了函数的入口地址 |
/* 调用别人提供的动态库 */ #include <stdio.h> #include <stdlib.h> int main(void) { //客户端初始化 获取handle上下 void *handle = NULL; char sendBuf[20] = "abcdefg"; char recvBuf[20] = {0}; int sendBufLen = 8; int recvBufLen = 0; int ret = cltSocketInit(&handle /*out*/); if (ret != 0) { printf("func cltSocketInit() err: %d\n", ret); return ret; } //客户端发报文 ret = cltSocketSend(handle /*in*/, sendBuf /*in*/, sendBufLen /*in*/); if (ret != 0) { printf("func cltSocketSend() err: %d\n", ret); return ret; } //客户端收报文 ret = cltSocketRev(handle /*in*/, recvBuf /*in*/, &recvBufLen /*in out*/); if (ret != 0) { printf("func cltSocketRev() err: %d\n", ret); return ret; } printf("recvBuf: %s\n", recvBuf); printf("recvBufLen: %d\n", recvBufLen); //客户端释放资源 ret = cltSocketDestory(handle/*in*/); if (ret != 0) { printf("func cltSocketDestory() err: %d\n", ret); return ret; } return 0; } |
5.动态库开发环境搭建
注:创建工程时勾选应用程序类型为DLL,其他没了。 |
6.动态库核心代码编写
第一套api的实现,第二套类似,这里不实现了。 主要要使用__declspec(dllexport)来修饰函数。 |
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct _SCK_HANDLE { char version[16]; char serverip[16]; int serverport; char *pBuf; int buflen ; }SCK_HANDLE; //------------------第一套api接口---Begin--------------------------------// //客户端初始化 获取handle上下 __declspec(dllexport) int cltSocketInit(void **handle /*out*/) { int ret = 0; SCK_HANDLE *sh = NULL; if (handle == NULL) { ret = -1; printf("func cltSocketInit() err: %d\n", ret); return ret; } sh = (SCK_HANDLE *)malloc(sizeof(SCK_HANDLE)); if (sh == NULL) { ret = -2; printf("func cltSocketInit() malloc err: %d\n", ret); return ret; } strcpy(sh->version, "1.0.1"); strcpy(sh->serverip, "192.168.1.1"); sh->serverport = 80; *handle = sh; return ret; } //客户端发报文 __declspec(dllexport) int cltSocketSend(void *handle /*in*/, unsigned char *buf /*in*/, int buflen /*in*/) { int ret = 0; SCK_HANDLE *sh = NULL; if (handle == NULL || buf == NULL) { ret = -3; printf("func cltSocketSend() err: %d\n", ret); return ret; } sh = (SCK_HANDLE *)handle; sh->pBuf = (char *)malloc(buflen * sizeof(char)); if (sh->pBuf == NULL) { ret = -2; printf("func cltSocketSend() malloc err: %d\n", ret); return ret; } strcpy(sh->pBuf, (const char *)buf); sh->buflen = buflen; return ret; } //客户端收报文 __declspec(dllexport) int cltSocketRev(void *handle /*in*/, unsigned char *buf /*in*/, int *buflen /*in out*/) { int ret = 0; SCK_HANDLE *sh = NULL; if (handle == NULL || buf == NULL || buflen == NULL) { ret = -4; printf("func cltSocketRev() err: %d\n", ret); return ret; } sh = (SCK_HANDLE *)handle; strcpy((char *)buf, sh->pBuf); *buflen = sh->buflen; return ret; } //客户端释放资源 __declspec(dllexport) int cltSocketDestory(void *handle/*in*/) { int ret = 0; SCK_HANDLE *sh = NULL; if (handle == NULL) { ret = -1; printf("func cltSocketDestory() err: %d\n", ret); return ret; } sh = (SCK_HANDLE *)handle; if (sh->pBuf != NULL) { free(sh->pBuf); } free(sh); return ret; } |
7.动态库设计和实现加日志
printf换成log |
将上面那个例子的printf换掉即可。如: 1 ITCAST_LOG(__FILE__, __LINE__, LogLevel[4], 4,"func cltSocketDestory() err: %d\n", ret); |