zoukankan      html  css  js  c++  java
  • 封装socketclient动态链接库

    一 生成DLL

    1 VS2017中新建项目,选择Visual C++ -> Windows桌面 -> 动态链接库

     项目名称输入socketclient,点击确定。

    2 删除vs默认创建的dllmain.c,stdafx.h,stdafx.c,targetver.h等文件(照顾VS2013等低版本)

    3 配置C环境

      右键项目 -> 属性 -> C/C++ -> 预编译头 -> 预编译头:改成 创建;

      右键项目 -> 属性 -> C/C++ -> 高级 -> 编译  -> 编译为:修改成编译为C代码。点击确定保存

    4 在socketclient.h中写函数声明,在socketclient.c中写函数的实现及导出函数

    5 点击生成 -> 生成解决方案

      会生成socketclient.dll,socketclient.lib等文件

    socketclient.h代码如下:

    //written by  wangbaoming1999@163.com
    //20140323 23:10
    /*
    下面定义了一套socket客户端发送报文接受报文的api接口
    请写出这套接口api的调用方法
    */
    
    #ifndef _INC_Demo01_H
    #define _INC_Demo01_H
    
    #ifdef  __cplusplus
    extern "C" {
    #endif
        
        //------------------第一套api接口---Begin--------------------------------//
        //客户端初始化 获取handle上下
        int cltSocketInit(void **handle /*out*/); 
        
        //客户端发报文
        int cltSocketSend(void *handle /*in*/, unsigned char *buf /*in*/,  int buflen /*in*/);
        
        //客户端收报文
        int cltSocketRev(void *handle /*in*/, unsigned char *buf /*in*/, int *buflen /*in out*/);
        
        //客户端释放资源
        int cltSocketDestory(void *handle/*in*/);
        //------------------第一套api接口---End-----------------------------------//
        
        
        //------------------第二套api接口---Begin--------------------------------//
        int cltSocketInit2(void **handle); 
    
        //客户端发报文
        int cltSocketSend2(void *handle, unsigned char *buf,  int buflen);
        //客户端收报文
        int cltSocketRev2(void *handle, unsigned char **buf, int *buflen);
        int cltSocketRev2_Free(unsigned char **buf);
        //客户端释放资源
    
        int cltSocketDestory2(void **handle);
        //------------------第二套api接口---End--------------------------------//
        
    #ifdef  __cplusplus
    }
    #endif
    
    #endif  /* _INC_Demo01_H */

    别忘了在要导出的函数前加__declspec(dllexport)

    socketclient.c中代码如下 :

    #define  _CRT_SECURE_NO_WARNINGS 
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
    #include "itcastlog.h"
    
    typedef struct _SCK_HANDLE
    {
        char    version[64];
        char    ip[128];
        int        port;
        unsigned char    *p;
        int        plen;
    }SCK_HANDLE; //动态库 内部的数据类型 ,不想让测试程序(上层应用知道)
    //数据类型的封装
    
    __declspec(dllexport)
    int cltSocketInit(void **handle /*out*/)
    {
        int        ret = 0;
        SCK_HANDLE *hdl = NULL;
        ITCAST_LOG(__FILE__, __LINE__, LogLevel[2], ret, "func cltSocketInit() Begin 22222:%d", ret);
    
        hdl = (SCK_HANDLE *)malloc(sizeof(SCK_HANDLE));
        if (hdl == NULL)
        {
            ret = -1;
            ITCAST_LOG(__FILE__, __LINE__, LogLevel[4], ret, "func cltSocketInit() err:%d", ret);
            return ret;
        }
        memset(hdl, 0, sizeof(SCK_HANDLE)); //把指针所指向的内存空间 赋值成 0;
    
        strcpy(hdl->ip, "192.168.6.254");
        hdl->port = 8081;
        *handle = hdl;
    
        ITCAST_LOG(__FILE__, __LINE__, LogLevel[2], ret, "func cltSocketInit() End:%d 
    ", ret);
    
        return ret;
    }
    
    //客户端发报文
    __declspec(dllexport)
    int cltSocketSend(void *handle /*in*/, unsigned char *buf /*in*/,  int buflen /*in*/)
    {
        int        ret = 0;
        SCK_HANDLE *hdl = NULL;
    
        if (handle==NULL || buf==NULL )
        {
            ret = -1;
            ITCAST_LOG(__FILE__, __LINE__, LogLevel[4], ret, "func cltSocketSend() err:%d
      (handle==NULL || buf==NULL ) ", ret);
            return ret;
        }
        
        hdl = (SCK_HANDLE *)handle;
    
        hdl->p = (unsigned char *)malloc(buflen *sizeof(unsigned char));
        if (hdl->p == NULL)
        {
            ret = -2;
            ITCAST_LOG(__FILE__, __LINE__, LogLevel[4], ret, "func cltSocketSend() err: buflen:%d ", buflen);
            ITCAST_LOG(__FILE__, __LINE__, LogLevel[4], ret, "func cltSocketSend() err:%d
      (unsigned char *)malloc(buflen *sizeof(unsigned char) ", ret);
            return ret;
        }
        memcpy(hdl->p, buf, buflen);
        hdl->plen = buflen;
    
        return 0;
    }
    
    //客户端收报文
    __declspec(dllexport)
    int cltSocketRev(void *handle /*in*/, unsigned char *buf /*in*/, int *buflen /*in out*/)
    {
        int        ret = 0;
        SCK_HANDLE *hdl = NULL;
    
        if (handle==NULL || buf==NULL  ||buflen==NULL)
        {
            ret = -1;
            ITCAST_LOG(__FILE__, __LINE__, LogLevel[4], ret, "func cltSocketRev() err:%d
      (handle==NULL || buf==NULL ) ", ret);
            return ret;
        }
        hdl = (SCK_HANDLE *)handle;
    
        memcpy(buf, hdl->p, hdl->plen);
        *buflen =  hdl->plen;
    
        return ret;
    }
    
    //客户端释放资源
    __declspec(dllexport)
    int cltSocketDestory(void *handle/*in*/)
    {
        int        ret = 0;
        SCK_HANDLE *hdl = NULL;
    
        if (handle==NULL )
        {
            ret = -1;
            ITCAST_LOG(__FILE__, __LINE__, LogLevel[4], ret, "func cltSocketDestory() err:%d
      (handle==NULL || buf==NULL ) ", ret);
            return ret;
        }
        hdl = (SCK_HANDLE *)handle;
    
        if (hdl->p)
        {
            free(hdl->p);
        }
        free(hdl);
    
        return ret;
    }
    
    
    //-----------------------第二套api函数--------------------------------*/
    __declspec(dllexport)
    int cltSocketInit2(void **handle)
    {
        return cltSocketInit(handle);
    }
    
    //客户端发报文
    __declspec(dllexport)
    int cltSocketSend2(void *handle, unsigned char *buf,  int buflen)
    {
        return cltSocketSend(handle, buf, buflen);
    }
    
    //客户端收报文
    __declspec(dllexport)
    int cltSocketRev2(void *handle, unsigned char **buf, int *buflen)
    {
        int        ret = 0;
        SCK_HANDLE *hdl = NULL;
        unsigned char        *tmp = NULL;
    
        if (handle==NULL || buf==NULL  ||buflen==NULL)
        {
            ret = -1;
            ITCAST_LOG(__FILE__, __LINE__, LogLevel[4], ret, "func cltSocketRev2() err:%d
      (handle==NULL || buf==NULL ) ", ret);
            return ret;
        }
        hdl = (SCK_HANDLE *)handle;
    
        tmp = (unsigned char *)malloc(hdl->plen);
        if (tmp == NULL)
        {
            ret = -2;
            ITCAST_LOG(__FILE__, __LINE__, LogLevel[4], ret, "func cltSocketRev2() err:%d
      (malloc err ) ", ret);
            return ret;
        }
    
        memcpy(tmp, hdl->p, hdl->plen);
        *buflen =  hdl->plen;
    
        *buf = tmp; //间接赋值
        return ret;
    }
    
    __declspec(dllexport)
    int cltSocketRev2_Free(unsigned char **buf)
    {
        if (buf == NULL)
        {
            return -1;
        }
        if (*buf != NULL)
        {
            free(*buf);
        }
        *buf = NULL; //*实参的地址  去间接的修改实参的值  重新初始化NULL
        return 0;
    }
    
    //客户端释放资源
    __declspec(dllexport)
    int cltSocketDestory2(void **handle)
    {
        SCK_HANDLE *tmp = NULL;
        if (handle==NULL)
        {
            return -1;
        }
        tmp = *handle; 
        if (tmp != NULL)
        {
            if (tmp->p)
            {
                free(tmp->p);
                tmp->p = NULL;
            }
            free(tmp);
        }
        *handle = NULL; //*实参的地址  去间接的修改实参的值  重新初始化NULL
    
        return 0;
    }

    二 使用DLL

    创建空项目,创建testsocket.c。

    ①把socketclient.h,socketclient.dll,socketclient.lib复制到testsocket.c的同目录下。添加现有项添加socketclient.h

    ②右键项目 -> 属性 -> 链接器 -> 输入 -> 附加依赖项:加入mysocketclient.lib

    然后就可以在testsocket.c中调用dll中的函数了,即使不使用dllimport关键字也可以。

    PS:开着二个项目的vs,在testsocket.c中下断点,F11进入cltSocketInit等接口会发现,VS调试可以进入DLL中的代码。

  • 相关阅读:
    伪造mysql服务端实现任意读取
    客户端session安全问题(flask)
    systemd教程
    MySQL的一些常用基本命令的使用说明
    AMD、CMD、CommonJs和ES6的区别
    for in与for of的区别,以及forEach,map,some,every,filter的区别
    EcmaScript 6 十大常用特性
    单行省略号与多行省略号
    Array.prototype.slice.call()详解及转换数组的方法
    返回顶部
  • 原文地址:https://www.cnblogs.com/fengxing999/p/12411186.html
Copyright © 2011-2022 走看看