用函数指针指向要调用的函数,并进行调用_C调用lua「建议收藏」

(35) 2023-09-17 17:12

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说用函数指针指向要调用的函数,并进行调用_C调用lua「建议收藏」,希望能够帮助你!!!。

1、 新建空项目,命名为RF_Drive,这个作为底层的驱动。

用函数指针指向要调用的函数,并进行调用_C调用lua「建议收藏」_https://bianchenghao6.com/blog__第1张

2、 添加MyDrive.c文件,向文件中添加代码,模拟驱动一些函数,代码如下:

思路:

EncData和DecData实现信息的加密和解密,由于不同厂家的设备,加密和解密的方式不同,所以不能在底层驱动中实现,需要不同的厂家在自己的函数库中实现。厂家和驱动约定好相同的接口,将函数通过指针传进来,实现函数的回调。

#define _CRT_SECURE_NO_WARNINGS

#include <stdlib.h>

#include <string.h>

#include <stdio.h>

//完成发送报文的时候,进行数据加密

//定义函数指针类型 通过函数指针类型 来约定 厂商 去实现 加密解密函数的原型

typedef int(*EncData)(unsigned char *in, int inlen, unsigned char *out, int *outlen);

typedef int(*DecData)(unsigned char *in, int inlen, unsigned char *out, int *outlen);

typedef struct _Sck_Handle

{

char version[16];

char ip[16];

int port;

unsigned char *p;

int len;

char *p2;

}Sck_Handle;

int socketclient_sendAndEnc1(void *handle, unsigned char *buf, int buflen, EncData encDataCallback)

{

int ret = 0;

unsigned char cryptbuf[4096];

int cryptbuflen = 4096;

Sck_Handle *tmpHandle = NULL;

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

{

ret = -1;

printf("func socketclient_sendAndEnc1() err :%d check handle == NULL err \n", ret);

return ret;

}

ret = encDataCallback(buf, buflen, cryptbuf, &cryptbuflen); //间接的调用子任务

if (ret != 0)

{

ret = -2;

printf("func socketclient_sendAndEnc1() err :%d check handle == NULL err \n", ret);

return ret;

}

tmpHandle = (Sck_Handle *)handle;

tmpHandle->len = cryptbuflen;

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

if (tmpHandle->p == NULL)

{

ret = -3;

printf("func socketclient_sendAndEnc1() err :%d mallocerr \n", ret);

return ret;

}

//把加密的明文 缓存到 内存中

memcpy(tmpHandle->p, cryptbuf, cryptbuflen);

return 0;

}

//socket客户端环境初始化

int socketclient_init(void **handle)

{

int ret = 0;

Sck_Handle *tmpHandle = NULL;

if (handle == NULL)

{

ret = -1;

printf("func socketclient_init() err :%d check handle == NULL err \n", ret);

return ret;

}

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

if (tmpHandle == NULL)

{

ret = -2;

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

return ret;

}

memset(tmpHandle, 0, sizeof(Sck_Handle));

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

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

tmpHandle->port = 8081;

//间接赋值

*handle = tmpHandle;

return ret;

}

//socket报文发送

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 ) \n", 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 \n", ret, buflen);

return ret;

}

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

return ret;

}

//socket报文接受

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 ) \n", ret);

return ret;

}

tmpHandle = (Sck_Handle *)handle;

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

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

return ret;

}

//socket环境释放

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;

}

3、 添加MyDrive.h文件。

#ifndef _INC_MYDRIVE_H__

#define _INC_MYDRIVE_H__

#define Import_SSS

#ifdef Import_SSS

#define API _declspec(dllexport)

#else

#define API _declspec(dllimport)

#endif

#ifdef __cplusplus

extern "C" {

#endif

//1 数据类型的封装

//2 handle的概念: 底层库的内存资源,记录着函数运行的上下文信息..

//3 底层库提供的是一种机制, 而不是满足某一个人的策略

//完成发送报文的时候,进行数据加密

//定义函数指针类型 通过函数指针类型 来约定 厂商 去实现 加密解密函数的原型

typedef int(*EncData)(unsigned char *in, int inlen, unsigned char *out, int *outlen);

typedef int(*DecData)(unsigned char *in, int inlen, unsigned char *out, int *outlen);

API

int socketclient_init(void **handle);

API

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

API

int socketclient_sendAndEnc1(void *handle, unsigned char *buf, int buflen, EncData encDataCallback);

API

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

API

int socketclient_destory(void *handle);

#ifdef __cplusplus

}

#endif

#endif

完成后,右键项目,将配置类型改为dll动态链接库。

4、 新建TestDrive工程,测试底层dll。将生成的RF_Drive.dll、RF_Drive.lib和MyDrive.h文件放到工程目录下面。

用函数指针指向要调用的函数,并进行调用_C调用lua「建议收藏」_https://bianchenghao6.com/blog__第2张

用函数指针指向要调用的函数,并进行调用_C调用lua「建议收藏」_https://bianchenghao6.com/blog__第3张

5、 将RF_Drive链接到TestDrive。选择输入,然后选择附加依赖项,将RF_Drive.lib添加进去,然后点击确定。

用函数指针指向要调用的函数,并进行调用_C调用lua「建议收藏」_https://bianchenghao6.com/blog__第4张

6、 将MyDrive.h包含到项目,然后新建Test.c文件,在Test.c中写入测试代码。代码如下:

思路:

在调用者实现加密算法Hw_EncData,不同的调用者,实现加密算法的方式不同,需要调用者自己实现,然后将函数的指针传递给底层驱动。

#define _CRT_SECURE_NO_WARNINGS

#include <stdlib.h>

#include <string.h>

#include <stdio.h>

#include "MyDrive.h"

int Hw_EncData(unsigned char *in, int inlen, unsigned char *out, int *outlen)

{

printf("func Hw_EncData begin....\n ");

strcpy((char *)out, "123456789");

*outlen = 9;

printf("func Hw_EncData end....\n ");

return 0;

}

void 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 \n ", ret);

goto End;

}

//客户端发报文

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

ret = socketclient_sendAndEnc1(handle, buf, buflen, Hw_EncData);

if (ret != 0)

{

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

goto End;

}

//客户端收报文

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

if (ret != 0)

{

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

goto End;

}

End:

//客户端释放资源

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

printf("hello...\n");

system("pause");

printf("hello...\n");

system("pause");

return;

}

运行结果如下:

用函数指针指向要调用的函数,并进行调用_C调用lua「建议收藏」_https://bianchenghao6.com/blog__第5张

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

上一篇

已是最后文章

下一篇

已是最新文章

发表回复