编写DLL代码

新建工程

新建空项目工程

点击确定。然后右键项目选择新建项。

出现下图,选择头文件。

再次选择新建项,选中C++文件,将其改为MySocketClient.c,然后选择添加。

到这里,新建工程就完成了。

然后右键项目,选择属性 将配置类型改为动态库(.dll)

编写头文件MySocketClient.h

#ifndef _INC_MYSOCKETCLIENT_H_

#define _INC_MYSOCKETCLIENT_H_

#define Import_SSS

#ifdef Import_SSS

#define API _declspec(dllexport)

#else

#define API _declspec(dllimport)

#endif

#ifdef _cplusplus//extern"C" 来告诉编译器:这是一个用C写成的库文件,请用C的方式来链接它们。

extern "C" {

#endif // _cplusplus

API//导出函数,让外界调用。

int socketClient_Init(void **handle);

API

int socketClient_Send(void *handle, unsigned char *buf, int buflen);

API

int socketClient_Recv(void *handle, unsigned char *buf, int *buflen);

API

int socketClient_Destory(void *handle);

#ifdef _cplusplus

}

#endif // _cplusplus

#endif //_INC_MYSOCKETCLIENT_H_

编写MySocketClient.c

#define _CRT_SECURE_NO_WARNINGS

#include

#include

#include

#include "MySocketClient.h"

typedef struct _Sck_Handle

{

char version[16];

char ip[16];

int port;

unsigned char *p;

int len;

}Sck_Handle;//定义Handle的结构体。

int socketClient_Init(void **handle)

{

int ret = 0;

Sck_Handle *tmpHandle = NULL;

if (handle == NULL)

{

ret = -1;

printf("[socketClient_Init] err %d handle=NULL ", ret);

return ret;

}

tmpHandle = (Sck_Handle *)malloc(sizeof(Sck_Handle));

if (tmpHandle == NULL)

{

ret = -2;

printf("[socketClient_Init] err:%d malloc err ", ret);

}

memset(tmpHandle, 0, sizeof(Sck_Handle));//初始化结构体。

strcpy(tmpHandle->version, "1.0.0.1");

strcpy(tmpHandle->ip, "192.168.12.121");

tmpHandle->port = 11111;

*handle = tmpHandle;

return ret;

}

socket报文发送

//__declspec(dllexport)

int socketClient_Send(void *handle, unsigned char *buf, int buflen)

{

int ret = 0;

Sck_Handle *tmpHandle = NULL;

if (handle == NULL || buf == NULL || buflen <= 0)

{

ret = -2;

printf("func socketclient_send() err :%d (handle == NULL || buf==NULL || buflen <=0 ) ", ret);

return ret;

}

tmpHandle = (Sck_Handle *)handle;

tmpHandle->len = buflen;

tmpHandle->p = (unsigned char *)malloc(buflen);

if (tmpHandle->p == NULL)

{

ret = -2;

printf("func socketclient_send() err :%d malloc len:%d ", ret, buflen);

return ret;

}

memcpy(tmpHandle->p, buf, buflen); //数据的缓存到内存

printf("接收到发送数据是%s ", tmpHandle->p);

return ret;

}

socket报文接受

//__declspec(dllexport)

int socketClient_Recv(void *handle, unsigned char *buf, int *buflen)

{

int ret = 0;

Sck_Handle *tmpHandle = NULL;

if (handle == NULL || buf == NULL || buflen == NULL)

{

ret = -2;

printf("func socketclient_recv() err :%d (handle == NULL || buf==NULL || buflen==NULL ) ", ret);

return ret;

}

tmpHandle = (Sck_Handle *)handle;

memcpy(buf, tmpHandle->p, tmpHandle->len);

*buflen = tmpHandle->len; //间接赋值 告诉调用者 收到的数据的长度

printf("数据长度是%d ", tmpHandle->len);

return ret;

}

socket环境释放

//__declspec(dllexport)

int socketClient_Destory(void *handle)

{

int ret = 0;

Sck_Handle *tmpHandle = NULL;

if (handle == NULL)

{

return -1;

}

tmpHandle = (Sck_Handle *)handle;

if (tmpHandle->p != NULL)

{

free(tmpHandle->p); //释放结构体 成员域的 指针所指向的内存空间

}

free(tmpHandle); //释放结构体内存

return 0;

}

然后右键编译工程。在Debug文件夹下面就可以看到生成的dll

动态调用

动态调用,使用LoadLibrary方法加载dll。

新建C++控制台应用程序

新建完成后,将编译好的dll文件、lib文件和h文件放到工程下面。

右键项目属性,将字符集改为使用多字节字符集。

下面是调用dll的代码。

#define _CRT_SECURE_NO_WARNINGS

#include

#include

#include

using namespace std;

//定义指针函数

typedef int(*SOCLETCLIENT_INIT)(void **handle);

typedef int(*SOCKETCLIENT_SEND)(void *handle, unsigned char *buf, int buflen);

typedef int(*SOCKETCLIENT_RECV)(void *handle, unsigned char *buf, int *buflen);

typedef int(*SOCKETCLIENT_DESTORY)(void *handle);

int main()

{

HINSTANCE hInstance;

hInstance = LoadLibrary("MySocketClient.dll");

SOCLETCLIENT_INIT socketClient_Init= (SOCLETCLIENT_INIT)GetProcAddress(hInstance, "socketClient_Init");

SOCKETCLIENT_SEND socketClient_Send=(SOCKETCLIENT_SEND)GetProcAddress(hInstance, "socketClient_Send");;

SOCKETCLIENT_RECV socketClient_Recv= (SOCKETCLIENT_RECV)GetProcAddress(hInstance, "socketClient_Recv");;

SOCKETCLIENT_DESTORY socketClient_Destory= (SOCKETCLIENT_DESTORY)GetProcAddress(hInstance, "socketClient_Destory");;

unsigned char buf[1024];

int buflen;

unsigned char out[1024];

int outlen;

void *handle = NULL;

int ret = 0;

strcpy((char *)buf, "aaaaAAAAAFFffffffdddddddd");

buflen = 9;

//客户端初始化 获取handle上下

ret = socketClient_Init(&handle /*out*/);

if (ret != 0)

{

printf("func socketclient_init() err:%d ", ret);

goto End;

}

//客户端发报文

ret = socketClient_Send(handle /*in*/, buf /*in*/, buflen /*in*/);

if (ret != 0)

{

printf("func socketclient_send() err:%d ", ret);

goto End;

}

//客户端收报文

ret = socketClient_Recv(handle /*in*/, out /*in*/, &outlen/*in out*/);

if (ret != 0)

{

printf("func socketclient_recv() err:%d ", ret);

goto End;

}

printf("接收到的数据长度是%d ",outlen);

End:

//客户端释放资源

ret = socketClient_Destory(handle/*in*/);

if (hInstance != NULL)

{

FreeLibrary(hInstance);

hInstance = NULL;

}

printf("hello...");

system("pause");

return 0;

}

使用

#define _CRT_SECURE_NO_WARNINGS

#include

#include

#include

using namespace std;

#pragma comment(lib,"MySocketClient.lib")

extern "C"

{

int socketClient_Init(void **handle);

int socketClient_Send(void *handle, unsigned char *buf, int buflen);

int socketClient_Recv(void *handle, unsigned char *buf, int *buflen);

int socketClient_Destory(void *handle);

}

int main()

{

unsigned char buf[1024];

int buflen;

unsigned char out[1024];

int outlen;

void *handle = NULL;

int ret = 0;

strcpy((char *)buf, "aaaaAAAAAFFffffffdddddddd");

buflen = 9;

//客户端初始化 获取handle上下

ret = socketClient_Init(&handle /*out*/);

if (ret != 0)

{

printf("func socketclient_init() err:%d ", ret);

goto End;

}

//客户端发报文

ret = socketClient_Send(handle /*in*/, buf /*in*/, buflen /*in*/);

if (ret != 0)

{

printf("func socketclient_send() err:%d ", ret);

goto End;

}

//客户端收报文

ret = socketClient_Recv(handle /*in*/, out /*in*/, &outlen/*in out*/);

if (ret != 0)

{

printf("func socketclient_recv() err:%d ", ret);

goto End;

}

printf("接收到的数据长度是%d ", outlen);

End:

//客户端释放资源

ret = socketClient_Destory(handle/*in*/);

printf("hello...");

system("pause");

return 0;

}

静态调用

静态调用,使用lib文件调用

#define _CRT_SECURE_NO_WARNINGS

#include

#include

#include

using namespace std;

#pragma comment(lib,"MySocketClient.lib")

extern "C"

{

int socketClient_Init(void **handle);

int socketClient_Send(void *handle, unsigned char *buf, int buflen);

int socketClient_Recv(void *handle, unsigned char *buf, int *buflen);

int socketClient_Destory(void *handle);

}

int main()

{

unsigned char buf[1024];

int buflen;

unsigned char out[1024];

int outlen;

void *handle = NULL;

int ret = 0;

strcpy((char *)buf, "aaaaAAAAAFFffffffdddddddd");

buflen = 9;

//客户端初始化 获取handle上下

ret = socketClient_Init(&handle /*out*/);

if (ret != 0)

{

printf("func socketclient_init() err:%d ", ret);

goto End;

}

//客户端发报文

ret = socketClient_Send(handle /*in*/, buf /*in*/, buflen /*in*/);

if (ret != 0)

{

printf("func socketclient_send() err:%d ", ret);

goto End;

}

//客户端收报文

ret = socketClient_Recv(handle /*in*/, out /*in*/, &outlen/*in out*/);

if (ret != 0)

{

printf("func socketclient_recv() err:%d ", ret);

goto End;

}

printf("接收到的数据长度是%d ", outlen);

End:

//客户端释放资源

ret = socketClient_Destory(handle/*in*/);

printf("hello...");

system("pause");

return 0;

}

运行结果:

.net core 调用c dll_C++ 调用C封装DLL库的两种方式相关推荐

  1. 主程序调用动态库的两种方式,动态库调用主程序的函数

    主程序调用动态库有两种方式,即隐式调用和显式调用. 隐式调用就是共享方式,程序一开始运行就调进去.在链接时候用如下的方式链接动态库:gcc -o main main.o -L./lib -ltest( ...

  2. C语言调用so动态库的两种方式

    方式1:类似静态库的调用(使用头文件) 这种方式生成的程序会在启动时候就加载so动态库. add.h int add(int x, int y); add.c #include "add.h ...

  3. Vue父组件调用子组件的方法并传参的两种方式(用$refs.refName.functionName、window.function)

    如需了解儿子怎么控制老子的,传送门:https://s-z-q.blog.csdn.net/article/details/120094689 父组件father.vue <template&g ...

  4. 微信小程序封装wx.request接口(两种方式)

    方式一:在根目录新建一个api.js的文件用于存放wx.request的代码 api.js const app = getApp(); let postApi = function (apiUrl, ...

  5. react 调用 html5,React-Native Webview 和H5交互的两种方式

    React-Native WebView 和H5交互有两种方式: 方式1:RN Webview 向H5注入JS 此方式可作为Webview向H5端传递数据. RN Webview 有以下属性,可以注入 ...

  6. [js] axios为什么可以使用对象和函数两种方式调用?是如何实现的?

    [js] axios为什么可以使用对象和函数两种方式调用?是如何实现的? axios 源码 初始化 看源码第一步,先看package.json.一般都会申明 main 主入口文件. // packag ...

  7. C#动态调用WCF接口,两种方式任你选。

    REFERENCE FROM : http://www.cnblogs.com/Leo_wl/p/4762784.html 写在前面 接触WCF还是它在最初诞生之处,一个分布式应用的巨作. 从开始接触 ...

  8. Http调用第三方接口的两种方式实例《超详细!!!》***

    Http调用第三方接口的两种方式<超详细!!!>* 最近在公司做一些调用第三方接口的工作,查阅了一部分的资料和向前辈以及朋友请教,完成了第三方接口的调用,其实主要是通过第三方提供的文档,完 ...

  9. android不调用系统发送短信,android之两种方式调用短信发送接口

    释放双眼,带上耳机,听听看~! 相信很多程序员在开发程序的时候都会遇到短信调用端口的情况,今天是技术狗小编为大家带来的关于android之两种方式调用短信发送接口,希望对你学习这方面知识有帮助! an ...

最新文章

  1. 纳米孔测序高错误区域恢复率高达99%,肖传乐/刘奕志/王建新等在Nature子刊发表新校正组装算法
  2. 木七七施辰刚:我是这样将玩家次留提升了 5% 的
  3. 解决swiper-slide在ion-slide-box不滑动的问题(暂且这么描述)
  4. [Leetcode][第114题][JAVA][二叉树展开为链表][递归][迭代]
  5. 从信息检索顶会CIKM'20看搜索、推荐与计算广告新进展
  6. ruby array_Ruby中带有示例的Array.zip()方法
  7. 程序员都在用的IDEA插件(不断更新)
  8. java 缓冲流 刷新_java – 缓冲和刷新Apache Beam流数据
  9. 【C++ Primer】第六章(分支语句和逻辑操作符)
  10. 数据库无限层级分类设计
  11. AR VR 将如何深刻影响未来的城市化进程
  12. 基于MATLAB的指纹识别算法仿真实现
  13. 微信小程序如何更新云数据库
  14. QTP之reporter对象方法全解析
  15. MySQL函数 if 的使用
  16. 【剑指offer】JZ55 二叉树的深度 python
  17. android 开发 安卓系统主题设置
  18. 2015.8.23——张佳莉
  19. 逻辑回归LogisticRegression
  20. 华为手机备份的通讯录是什么文件_华为手机通讯录如何备份?

热门文章

  1. Idea日常使用记录
  2. handsontable pro 授权码 key 生成器(JS函数)(仅供学习交流)
  3. 利用 Hexo + Github 搭建自己的博客
  4. C#开发笔记之14-如何用C#计算闰年?
  5. C#LeetCode刷题之#257-二叉树的所有路径(Binary Tree Paths)
  6. 逻辑回归优点_逻辑回归:优点
  7. react hooks_React Hooks简介
  8. sql缩进提高语句的可读性_为什么要使用列缩进来提高代码的可读性
  9. php为什么要提前定义变量
  10. 用MATLAB玩转机器人--第六章 用MATLAB玩转单关节机器人