[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.动态库调用流程

步骤:

  1. 将lib,dll,.h文件拷贝到工程的.c的同级目录下
  2. 工程右键属性->配置属性->链接器->输入->附加依赖项
  3. 直接照着.h文件的函数声明调用函数即可

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);
posted @ 2015-01-07 08:29  IFPELSET  阅读(164)  评论(0编辑  收藏  举报