$ tree
.
├── dllcall.go
├── libdll.h
├── loaddll.c
└── loaddll.h
dllcall.go
package dlltest
/*
#include "loaddll.h"
#cgo LDFLAGS: -ldl
*/
import "C"
import (
"encoding/hex"
"errors"
"fmt"
"unsafe"
)
type DllCall struct {
}
var (
// 启用调试标记 1 启动调试 0 关闭调试
M_Conf_Debug = 1
)
func NewDllCall() *DllCall {
return &DllCall{}
}
// 计算哈希
func (o *DllCall) HashData(agmId int, iv string, src string) (string, error) {
agmID := C.int(agmId)
var hashValueByt [2048]byte
hashValueBytLen := C.int(len(hashValueByt))
bytIv, _ := hex.DecodeString(iv) //公钥
bytSrc, _ := hex.DecodeString(src) // 待哈希数据
//logs.Info("src= \n%v", src)
ret := C.HashData(
M_Conf_Debug,
agmID, /* 加密方案,1 国密算法 */
(*C.char)(unsafe.Pointer(&bytIv[0])), C.int(len(bytIv)), /* 字符串,向量 */
(*C.char)(unsafe.Pointer(&bytSrc[0])), C.int(len(bytSrc)), /* 字符串,待哈希数据 */
(*C.char)(unsafe.Pointer(&hashValueByt[0])), &hashValueBytLen) /* 出参: 字节缓冲区*/
if ret != 0 {
outButStr := ""
errmsg := fmt.Sprintf("c dll HashData call fail, ret=%v, errmsg=%v, msg=%v", ret, GetErrorMsg(int(ret)), outButStr)
return "", errors.New(errmsg)
}
hashValue := hex.EncodeToString(hashValueByt[:hashValueBytLen])
return hashValue, nil
}
func GetErrorMsg(errorCode int) string {
errorCodeMap := make(map[int]string)
errorCodeMap[-1] = "参数错误"
errorCodeMap[-2] = "结果数据缓冲区长度不足"
return errorCodeMap[errorCode]
}
---------------libdll.h
// 底层库操作接口说明
// 计算数据的hash值
// 返回值:
// >0: 计算成功, 返回结果数据的字节数
// <0: 计算失败, 错误代码
// 参数:
// [in]iv: 算法所需的初始化数据
// [in]iLen: iv数据的字节数
// [in]src: 所需哈希的数据
// [in]sLen: src数据的字节数
// [out]rslt: 返回结果数据
// [in/out]rLen: 期望的结果数据字节长度.如果输入值小于实际长度则返回实际所需的字节数,同时方法的返回值返回特殊值报告此种情况.
int HashData(char *iv, int iLen, char *src, int sLen, char *rslt, int *rLen);
-------------loaddll.h
// 计算哈希
int HashData(int ctl, int agmID, char *iv, int iLen, char *src, int sLen, char *rslt, int *rLen);
------------loaddll.c
#include "loaddll.h"
#include <dlfcn.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
// ----------- 预定义变量 ----------------
#define LIB_NAME "libdll.so" //library name
// 外部参数
char dll_name[]= LIB_NAME;
// 动态库句柄
void* dll_handle;
// 动态库load标记 0 成功
int dll_loaded = 1;
// 函数声明
void uint8_2_hex(char *source, int length, char *target) ;
int load_dll(const char* dllname, char* outbuf);
// 函数指针,计算Hash
typedef int (*fptr_HashData)(int agmID, char *iv, int iLen, char *src, int sLen, char *rslt, int *rLen);
// 计算哈希
int HashData(int ctl, int agmID, char *iv, int iLen, char *src, int sLen, char *rslt, int *rLen){
int callret = -1; //调用结果
int dllret = -1;
char buf[20480] = {0};
// 检测动态库是否加载,没有加载就自动加载
if(dll_loaded != 0)
{
char szOutMsg[256] = {0};
int b = load_dll(dll_name, szOutMsg);
if(b!=0)
{
callret = -1;
strcpy(rslt, szOutMsg);
*rLen = strlen(rslt);
return callret;
}
}
if(ctl)
{
// ------------- 打印参数
printf("--Debug--method(HashData)--> InputParam:\n");
printf("--> ctl: %d\n", ctl);
uint8_2_hex(iv,iLen, buf);
printf("--> iv[%ld]: %s\n", strlen(buf)/2, buf);
uint8_2_hex(src,sLen, buf);
printf("--> src[%ld]: %s\n",strlen(buf)/2, buf);
}
// 函数指针
fptr_HashData fptr = (fptr_HashData)dlsym(dll_handle, "HashData");
iLen = 0;
// 调用动态库函数
dllret = (*fptr)(agmID, iv, iLen, src, sLen, rslt, rLen);
if(ctl)
{
printf("--Debug--method(HashData)--> OutParam:\n");
printf("--> Ret=%d\n",dllret);
if(!dllret)
{
uint8_2_hex(rslt,*rLen, buf);
printf("--> hash[s,%ld==%d]: %s\n", strlen(buf)/2, *rLen, buf);
}
}
callret = dllret ;
return callret;
}
// 加载动态库
int load_dll(const char* dllname, char* outbuf)
{
// -------------- 得到当前路径 -----------
char buf[1024] = {0};
char *p = getcwd(buf,sizeof(buf));
char szFullPath[1200] = {0};
strcpy(szFullPath, buf);
strcat(szFullPath, "/lib/"); //第三方依赖库存放路径
strcat(szFullPath, dllname);
// ------------ 打开动态库 --------------
dll_handle = dlopen(szFullPath, 1);
if(dll_handle == 0){
memset(buf, 0, sizeof(buf));
sprintf(buf,"open dll fail, filename= %s", szFullPath);
strcpy(outbuf,buf);
return -1;
}
dll_loaded = 0;
return 0;
}
// ----------------- 工具函数 ----------------------
/**
* 字节数组转十六进制字符串
* @param source
* 字符数组
* @param length
* 字符数组长度
* @param target
* 字符串
*/
void uint8_2_hex(char *source, int length, char *target) {
char szbuf[10240] = {0};
for (int i = 0; i < length; i++) {
char buf[3]={0};
sprintf(buf, "%.2X", (unsigned char)source[i]);
strcat(szbuf, buf);
}
strcpy(target, szbuf);
}