golang 調用c庫


$ 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);
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM