C语言 动态库简单开发

动态库项目

//简单的动态库开发----报文发送
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

//定义上下文结构体
typedef struct _SCK_HANDLE{
    //定义报文IP
    char ipaddress[30];
    //定义报文端口
    char port[10];
    //定义报文接受数组
    unsigned char * buf;
    //定义报文长度
    int buflen;
}SCK_HANDLE;


//初始化上下文
_declspec(dllexport)
int cltSocketInit(void **handle/*out*/){
    int ERRO_MSG = 0;
    if (handle == NULL)
    {
        ERRO_MSG = 1;
        printf("handle==NULL 报文初始化失败 erro msg:%d
", ERRO_MSG);
        return ERRO_MSG;
    }
    //定义上下文指针
    SCK_HANDLE *shandle = NULL;
    //分配内存
    //详述:此处分配内存必须分配堆内存(malloc函数分配),这也正是malloc函数真正的用途所在
    //此处不可以分配栈内存,栈内存会被系统自动回收,但是报文的发送与接受所使用的上下文SCK_HANDLE,必须长时间存在
    //何时回收必须由用户决定,而不能随便的被回收
    //同样使用静态区也不合适,因为无法人为回收内存空间,必须等待电脑关机,综上所述,只能使用malloc函数分配内存
    shandle = (SCK_HANDLE *)malloc(sizeof(SCK_HANDLE));
    //重置内存空间
    memset(shandle, 0, sizeof(SCK_HANDLE));
    strcpy(shandle->ipaddress, "192.168.0.128");
    strcpy(shandle->port, "88");
    *handle = shandle;
    return ERRO_MSG;
}
//客户端发报文
_declspec(dllexport)
int cltSocketSend(void *handle/*in*/, unsigned char *buf/*in*/, int buflen/*in*/){
    int ERRO_MSG = 0;
    if (handle == NULL)
    {
        ERRO_MSG = 1;
        printf("handle==NULL handle不可以为NULL erro msg :%d
", ERRO_MSG);
        return ERRO_MSG;
    }
    if (buf == NULL)
    {
        ERRO_MSG = 2;
        printf("buf==NULL buf不可以为NULL erro msg :%d
", ERRO_MSG);
        return ERRO_MSG;
    }
    SCK_HANDLE *sh = NULL;
    sh = (SCK_HANDLE *)handle;
    //为报文字符开辟内存空间
    sh->buf = (char *)malloc(sizeof(char)*buflen);
    if (sh->buf == NULL)
    {
        ERRO_MSG = 3;
        printf("sh->buf==NULL 内存分配失败 erro msg :%d
", ERRO_MSG);
        return ERRO_MSG;
    }
    //给上下文中的报文字符赋值
    //memcpy()函数详解
    //函数原型
    //void *memcpy(void *dest, const void *src, size_t n);
    //功能
    //从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中
    //所需头文件
    //C语言:#include<string.h>
    //C++:#include<cstring>
    //返回值
    //函数返回指向dest的指针。
    //说明
    //1.source和destin所指的内存区域可能重叠,但是如果source和destin所指的内存区域重叠, 那么这个函数并不能够确保source所在重叠区域在拷贝之前不被覆盖。而使用memmove可以用来处理重叠区域。函数返回指向destin的指针.
    //2.如果目标数组destin本身已有数据,执行memcpy()后,将覆盖原有数据(最多覆盖n)。如果要追加数据,则每次执行memcpy后,要将目标数组地址增加到你要追加数据的地址。
    //注意:source和destin都不一定是数组,任意的可读写的空间均可。
    memcpy(sh->buf, buf, buflen);
    sh->buflen = buflen;
    return ERRO_MSG;
}
//客户端收报文
_declspec(dllexport)
int cltSocketRev(void *handle/*in*/, unsigned char **buf/*out*/, int *buflen/*out*/){
    int ERRO_MSG = 0;
    if (handle == NULL || buf == NULL || buflen == NULL)
    {
        ERRO_MSG = 1;
        printf("handle == NULL || buf == NULL || buflen==NULL erro msg:%d
", ERRO_MSG);
        return ERRO_MSG;
    }
    //定义临时上下文变量
    SCK_HANDLE *sh = NULL;
    sh = (SCK_HANDLE *)handle;
    //分配返回报文字符串内存
    char *cbuf = (char *)malloc(sizeof(char)*sh->buflen);
    memcpy(cbuf, sh->buf, sh->buflen);
    *buf = cbuf;
    *buflen = sh->buflen;
    //释放上下文中字符串数组的内存空间(至于具体应用还是看场景)
    if (sh->buf != NULL)
    {
        //释放内存
        free(sh->buf);
        //消除野指针
        sh->buf = NULL;
    }
    sh->buflen = 0;
    return ERRO_MSG;
}
//客户端释放资源
_declspec(dllexport)
int cltSocketDestory(void **handle){
    int ERRO_MSG = 0;
    if (handle == NULL)
    {
        ERRO_MSG = 1;
        printf("handle==NULL%d
", ERRO_MSG);
        return ERRO_MSG;
    }
    //转换类型
    SCK_HANDLE *sh = NULL;
    sh = (SCK_HANDLE *)(*handle);
    //判断字符串数组是否释放--严谨做法
    if (sh->buf!=NULL)
    {
        //释放内存
        free(sh->buf);
        //消除野指针
        sh->buf = NULL;
        //长度置零
        sh->buflen = 0;
    }
    if (sh != NULL)
    {
        //释放内存
        free(sh);
        //消除野指针
        sh = NULL;
    }
    return ERRO_MSG;
}

测试项目

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include"socketclientdll.h"



void main()
{
    int ret = 0;
    //初始化报文
    void *handle = NULL;
    ret = cltSocketInit(&handle);
    if (ret==0)
    {
        printf("报文初始化成功!
");
    }
    //发送报文
    unsigned char *str = "1234567890qwertyuiop";
    int buflen = 10;
    ret = cltSocketSend(handle, str, buflen);
    if (ret == 0)
    {
        printf("报文发送成功!
");
    }
    unsigned char *str2 = NULL;
    int buflen2 = 0;
    //接受报文
    ret = cltSocketRev(handle, &str2, &buflen2);
    if (ret == 0)
    {
        unsigned char *buf3 = (char *)malloc(sizeof(char)*12);
        memset(buf3,0,sizeof(char)*12);
        memcpy(buf3, str2, 10);
        //strcpy(buf3, str2);
        printf("报文接受成功!
");
        printf("接受报文:%s;报文长度是%d
", buf3, buflen2);
    }
    //释放上下文
    cltSocketDestory(&handle);
    printf("%p
", handle);
    system("pause");
}

效果图

原文地址:https://www.cnblogs.com/zhanggaofeng/p/5512909.html