因为 openssl 1.0.2 已不再维护,在进行 openssl 升级到 1.1.1 版本的时候,应用中有不少使用 openssl 的接口都需要进行相应的修改。
而修改最大的感受就是很多结构体都无法直接声明使用了,只能改为指针声明使用。
在 openssl 的 CHANGES 文档(该文档对于 openssl 的变更很有必要查看了解)中也有说明,如下:
Made EVP_MD_CTX, EVP_MD, EVP_CIPHER_CTX, EVP_CIPHER and HMAC_CTX opaque. For HMAC_CTX, the following constructors and destructors were added:
HMAC_CTX *HMAC_CTX_new(void); void HMAC_CTX_free(HMAC_CTX *ctx);
这里的关键字, opaque
不透明的
即你无法查看该结构体的组成,不清楚其有哪些成员变量。这个特性可以认为是 C 语言的封装。
使用示例:
#point.h
typedef struct point POINT;
POINT * new_point(int x, int y);
void free_point(POINT *a);
int cal_point_value(POINT *a);
#point.c
#include <stdio.h>
#include <stdlib.h>
typedef struct point
{
int x;
int y;
}POINT;
POINT * new_point(int x, int y)
{
POINT *p = malloc(sizeof(POINT));
if (NULL == p)
return NULL;
p->x = 2 * x;
p->y = 3 * y;
return p;
}
void free_point(POINT *a)
{
if (a != NULL)
free(a);
}
int cal_point_value(POINT *a)
{
return a->x + a->y;
}
#include <stdio.h>
#include "point.h"
int main(void)
{
int ret = -1;
POINT *p = NULL;
p = new_point(2, 4);
if (NULL == p)
return -1;
ret = cal_point_value(p);
printf("ret:%d\n", ret);
free_point(p);
return 0;
}
如果调用方像往常一样声明定义结构体,编译链接就会报错,如下:
错误提示 point.h 使用的是 forward declaration,即前置声明。
前置声明针对的都是不完整类型,如具体成员未明确的结构体,也就如错误提示说明的那样,variable has incomplete type 'POINT' (aka 'struct point')
如要使用不完整类型,都需以指针的方式声明使用。
使用不完整类型的好处:
调用方因不能直接定义 POINT 结构体,无法直接操作结构体成员变量,隐藏细节的同时避免了外部随意破坏结构体中成员变量的值,只能按提供方的接口去调用操作,保证操作的可预见性,而不会出现意料之外的错误。
不好的地方:
1、因为不能由调用方定义结构体,则结构体的定义申请操作放到了接口内部实现,相应的,调用方使用完之后,需要手动进行释放操作,而不像直接定义结构体变量,函数退出就自动释放了。
2、无法使用 sizeof 操作获取结构体的大小。