基于Openssl的SM2算法C语言实现问题——错误E0393——不允许指针指向不完整的类类型 "struct ECDSA_SIG_st"

因为毕业设计需要,在网上找到的基于Openssl的SM2算法C语言实现代码,在安装好Openssl1.1.1,环境搭建完成后,进行编译出现如下问题:

严重性 代码 说明 项目 文件 行 禁止显示状态
错误(活动) E0393 不允许指针指向不完整的类类型 "struct ECDSA_SIG_st"

sm2.h——》

static ECDSA_SIG *sm2_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *in_k, const BIGNUM *in_r, EC_KEY *eckey)
{
    int     ok = 0, i;
    BIGNUM *k=NULL, *s, *m=NULL,*tmp=NULL,*order=NULL;
    const BIGNUM *ck;
    BN_CTX     *ctx = NULL;
    const EC_GROUP   *group;
    ECDSA_SIG  *ret;
    //ECDSA_DATA *ecdsa;
    const BIGNUM *priv_key;
    BIGNUM *r,*x=NULL,*a=NULL;    //new added
    //ecdsa    = ecdsa_check(eckey);
    group    = EC_KEY_get0_group(eckey);
    priv_key = EC_KEY_get0_private_key(eckey);
    
    if (group == NULL || priv_key == NULL /*|| ecdsa == NULL*/)
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_PASSED_NULL_PARAMETER);
        return NULL;
    }

    ret = ECDSA_SIG_new();
    if (!ret)
    {
        ECDSAerr(EC_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
        return NULL;
    }

    s = ret->s; 
    r = ret->r;    /*这两句中的ret报错了*/

    if ((ctx = BN_CTX_new()) == NULL || (order = BN_new()) == NULL ||
        (tmp = BN_new()) == NULL || (m = BN_new()) == NULL || 
        (x = BN_new()) == NULL || (a = BN_new()) == NULL)
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    if (!EC_GROUP_get_order(group, order, ctx))
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_EC_LIB);
        goto err;
    }
//     for(i=0;i<dgst_len;i++)
//         printf("%02X",dgst[i]);
//      printf("\n");
    i = BN_num_bits(order);
    /* Need to truncate digest if it is too long: first truncate whole
     * bytes.
     */
    if (8 * dgst_len > i)
        dgst_len = (i + 7)/8;
    if (!BN_bin2bn(dgst, dgst_len, m))
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
        goto err;
    }
    /* If still too long truncate remaining bits with a shift */
    if ((8 * dgst_len > i) && !BN_rshift(m, m, 8 - (i & 0x7)))
    {
        ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
        goto err;
    }
//     fprintf(stdout,"m: ");
//     BNPrintf(m);
//     fprintf(stdout,"\n");
    do
    {
        if (in_k == NULL || in_r == NULL)
        {
            if (!sm2_sign_setup(eckey, ctx, &k, &x))
            {
                ECDSAerr(ECDSA_F_ECDSA_DO_SIGN,ERR_R_ECDSA_LIB);
                goto err;
            }
            ck = k;
        }
        else
        {
            ck  = in_k;
            if (BN_copy(x, in_r) == NULL)
            {
                ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_MALLOC_FAILURE);
                goto err;
            }
        }
        
        //r=(e+x1) mod n
        if (!BN_mod_add_quick(r, m, x, order))
        {
            ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
            goto err;
        }

//         BNPrintf(r);
//         fprintf(stdout,"\n");

        if(BN_is_zero(r) )
            continue;

        BN_add(tmp,r,ck);
        if(BN_ucmp(tmp,order) == 0)
            continue;
        
        if (!BN_mod_mul(tmp, priv_key, r, order, ctx))
        {
            ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
            goto err;
        }
        if (!BN_mod_sub_quick(s, ck, tmp, order))
        {
            ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
            goto err;
        }
        BN_one(a);
        //BN_set_word((a),1);

        if (!BN_mod_add_quick(tmp, priv_key, a, order))
        {
            ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
            goto err;
        }
        /* compute the inverse of 1+dA */
        if (!BN_mod_inverse(tmp, tmp, order, ctx))
        {
            ECDSAerr(EC_F_ECDSA_SIGN_SETUP, ERR_R_BN_LIB);
            goto err;    
        }
//         BNPrintf(tmp);
//         fprintf(stdout,"\n");

        if (!BN_mod_mul(s, s, tmp, order, ctx))
        {
            ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ERR_R_BN_LIB);
            goto err;
        }
        if (BN_is_zero(s))
        {
            /* if k and r have been supplied by the caller
             * don't to generate new k and r values */
            if (in_k != NULL && in_r != NULL)
            {
                ECDSAerr(ECDSA_F_ECDSA_DO_SIGN, ECDSA_R_NEED_NEW_SETUP_VALUES);
                goto err;
            }
        }
        else
            /* s != 0 => we have a valid signature */
            break;
    }
    while (1);

    ok = 1;
err:
    if (!ok)
    {
        ECDSA_SIG_free(ret);
        ret = NULL;
    }
    if (ctx)
        BN_CTX_free(ctx);
    if (m)
        BN_clear_free(m);
    if (tmp)
        BN_clear_free(tmp);
    if (order)
        BN_free(order);
    if (k)
        BN_clear_free(k);
    if (x)
        BN_clear_free(x);
    if (a)
        BN_clear_free(a);
    return ret;
}



ec.h——》

typedef struct ECDSA_SIG_st ECDSA_SIG;

/** Allocates and initialize a ECDSA_SIG structure
 *  \return pointer to a ECDSA_SIG structure or NULL if an error occurred
 */
ECDSA_SIG *ECDSA_SIG_new(void);  /*主要涉及到的结构体定义声明部分*/

由于专业问题 好久没碰过C语言了,百度这个错误都说是由于函数定义了但是没声明导致的,还有说是由于头文件没有包含,但是这些都检查过了没问题,于是考虑是否是结构体中变量问题,ret中是否有 r、s两个变量
查找openssl官网找到了ECDSA_SIG_new函数的介绍:

ECDSA_SIG是一个不透明的结构,由两个 BIGNUM 组成,用于表示 ECDSA 特征码的 r和 s 值(请参见 X9.62 或 FIPS 186-2)。
ECDSA_SIG_new() 分配一个空的ECDSA_SIG结构。注意:在 OpenSSL 1.1.0 之前,r和s组件已初始化。
ECDSA_SIG_free() 释放ECDSA_SIG结构sig。
ECDSA_SIG_get0() 返回sig中包含的r和s值的内部指针,并分别将它们存储在pr和ps中。指针pr或ps可以为 NULL,在这种情况下,不会返回相应的值。
值r, s也可以分别由相应的函数 ECDSA_SIG_get0_r() 和 ECDSA_SIG_get0_s() 分别检索。
可以通过调用 ECDSA_SIG_set0() 并将 r 和s的新值作为参数传递给函数来设置r和s值。调用此函数会将值的内存管理传输到ECDSA_SIG对象,因此在调用此函数后,不应直接释放已传入的值。

但是还是没明白是否ECDSA_SIG这个空的结构体中r、s已经进行了初始化定义?
也尝试过使用ECDSA_SIG_get0或ECDSA_SIG_getr或ECDSA_SIG_gets 函数直接调取r、s但是都无果

本人是第一次接触Openssl 希望各位能帮忙解决这个问题