站長資訊網
最全最豐富的資訊網站

詳解CGO項目中常用的數據轉換及使用

本文由golang教程欄目給大家介紹關于CGO實戰項目中常用的數據轉換和使用,希望對需要的朋友有所幫助!

前言

需要部署好相關環境和具備基本的知識點,這并非是一篇科普的文章,主要是針對實際項目中用到的類型轉換和使用,針對動態庫的函數調用參數傳遞和接收
1、GO環境,啟動支持CGO
2、事先安裝g++
3、看得懂GO和C的語法
4、最好會基本的makefile或者shell語法(表示我不懂,是個菜雞,只會看個大概)主要是自己調試C需要用到
如果大家是一清二白的,請點擊掃盲鏈接:chai2010.cn/advanced-go-programmin…

基本數據類型一覽

詳解CGO項目中常用的數據轉換及使用

由于GO支持 C語言的調用,所以只列出了和C的轉換,至于C++,需要轉換成C語言才可以成功調用。需要注意的是:每個C的變量都是限定在一個包內使用的,如果想跨包使用,請用GO封裝一層,否則會提示調用錯誤,找不到這個C變量。

項目中用到的數據類型轉換

go的string轉換成C

C的字符串就是一個字符數組的特例,簡單的說就是一個字符數組以0結尾的數組就是字符串,所以不屬于基本數據類型 。
C.CString是調用C的標準庫,申請了新的內存空間,需要調用C.free釋放,否則會內存泄漏。

    var  deviceIp string     cdeviceIp := C.CString(deviceIp)     defer C.free(unsafe.Pointer(cdeviceIp))
C的char * /char[] 轉換成go的string

調用C的標準庫 C.GoString,這個函數不會產生新的內存空間,創建的是一個副本,也不會釋放內存空間。

C的字節數組轉Go的string

比方說C的類型是:BYTE sSerialNumber[SERIALNO_LEN];
獲取的方式就是利用append添加字節到字符串

    serialNo := make([]byte, 0)     for _, v := range sSerialNumber {         if v != 0 {             serialNo = append(serialNo, byte(v))         }     }

注意前面提到的字符數組和字符串的區別。

Go的string轉C的字符數組

類型:CHAR szKeyFilePath[PU_CERT_FILE_PATH_MAX];

    var keyFilePath = "/home/docker/path/file.jpg"     for i, b := range keyFilePath {         szKeyFilePath[i] = C.CHAR(b)     }

聯合體的數據獲取

接華為攝像頭的數據回調的時候有聯合體類型數據的獲取,當作普通結構體獲取的時候編譯會一直提示找不到這個結構體,后面不得已,在C代碼里面獲取到聯合體的數據之后,轉換成基本數據類型,再重新Go調用。貼一個代碼片斷,人臉識別回調獲取的數據。不用糾結前后文,看數據類型的獲取就好。

void CGopfFaceSnapCallBack(CHAR *szBuffer, LONG lSize, void *pUsrData) {     PU_META_DATA *pstMetaData = 0;     int ret = Wrapper_IVS_User_GetMetaData(szBuffer, lSize, TARGET, &pstMetaData);     if (ret == PU_FALSE ){         return ;     }     PU_UserData *pstMetaUserData = pstMetaData->pstMetaUserData;     char  name[100]={0};     char  cardID[100]={0};     for(UINT uIndex = 0; uIndex < pstMetaData->usValidNumber; ++uIndex){        //printf("pstMetaData eType : %xn", pstMetaUserData[uIndex].eType);         if (pstMetaUserData[uIndex].eType == FACE_INFO){             strcpy(cardID, pstMetaUserData[uIndex].unMetaData.stFaceInfo.cardID);             strcpy(name, pstMetaUserData[uIndex].unMetaData.stFaceInfo.name);             printf("GopfFaceSnapCallBack unMetaData.stFaceInfo cardID : %sn", pstMetaUserData[uIndex].unMetaData.stFaceInfo.cardID);             printf("GopfFaceSnapCallBack unMetaData.stFaceInfo name : %sn", pstMetaUserData[uIndex].unMetaData.stFaceInfo.name);             GopfFaceSnapCallBack(pstMetaUserData[uIndex].unMetaData.stFaceInfo.cardID,pUsrData);             break ;         }     }     Wrapper_IVS_User_FreeMetaData(&pstMetaData);     return ;}

如果這段代碼換成Go的邏輯,直接在Go里面去讀取的話會提示unMetaData 找不到定義。有其他成功讀取方式的,還請告知。

C的回調函數的調用

1、先Go代碼實現數據類型一致的函數,利用//export 導出為C函數,如果發現回調沒進來,首先檢查一下數據類型是否正確,再檢查觸發條件是否滿足。這一步是為了在Go語言里面接收到C語言的回調數據,也就是回調后的數據是在這個函數里面獲取。
2、CGO調用C函數,有同事說這一步可以不用,直接在Go里面調用第一步的函數就可以,我還沒試過,公司祖傳的代碼就是這么寫的,也就直接照用了。
3、在GO語言里面當作常用函數直接調用就好。
看代碼示例:
C的函數聲明:

typedef VOID (CALLBACK *pfRealDataCallBack)(CHAR *szBuffer, LONG lSize, VOID *pUsrData);

第一步的代碼:

//export GopfRealDataCallBackfunc GopfRealDataCallBack(szBuffer *C.CHAR, lSize C.LONG, pUsrData unsafe.Pointer) {     fmt.Println(szBuffer,lSize,pUsrData)}

第二步:

extern void GopfRealDataCallBack(CHAR *szBuffer, LONG lSize, void *pUsrData);void CGopfRealDataCallBack(CHAR *szBuffer, LONG lSize, void *pUsrData){     return GopfRealDataCallBack(szBuffer,lSize,pUsrData);}

第三步:C.pfRealDataCallBack(C.CGopfRealDataCallBack),需要在import C 上聲明,否則調用不生效

void*和unsafe.Pointer

unsafe.Pointer號稱是所有數據類型的轉接橋梁,在語言層面兩個可以認為等同的,當碰到void*可以用unsafe.Pointer來接收或者傳遞,具體類型的轉換,需要根據實際類型做強轉。比方說:

lpOutBuff := unsafe.Pointer(C.malloc(1024))

這個1024看實際情況修改,不是萬能的。

結構體數組的傳遞

results := (*C.struct_name)(C.malloc(C.size_t(C.sizeof_struct_name * C.int(resLen))))     defer C.free(unsafe.Pointer(results))

struct_name換成具體的結構體名稱,申請了空間要釋放,GO檢測不到C的部分。

結構體數組遍歷獲取元素數據

    for i := 0; i < int(resLen); i++ {         result := (*C.struct_name)(unsafe.Pointer(uintptr(unsafe.Pointer(results)) + uintptr(i*C.sizeof_struct_name)))     }

struct_name換成具體的結構體名稱,uintptr是元素內存地址,根據偏移量獲取元素。go for i := 0; i < int(resLen); i++ { result := (*C.DetectFaceResult)(unsafe.Pointer(uintptr(unsafe.Pointer(results)) + uintptr(i*C.sizeof_DetectFaceResult))) }

贊(0)
分享到: 更多 (0)
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
亚洲av日韩av天堂影片精品| 日韩精品免费一线在线观看| 大桥未久在线精品视频在线| 狠狠入ady亚洲精品| 精品一卡2卡三卡4卡免费视频| 国产精品三级在线观看| 久久九九精品国产av片国产| 国产午夜亚洲精品国产成人小说 | 在线观看国产精品日韩av| 无码国产精品一区二区高潮| 国产成人精品免费视频大| 久热精品人妻视频| 国产真实乱人偷精品| 久久精品毛片免费观看| 亚洲AV日韩精品一区二区三区| 亚洲а∨精品天堂在线| 久久精品*5在热| 日韩电影免费在线观看视频| 国产精品大全国产精品| 青青草国产精品久久| 日韩精品一区二区午夜成人版| 国产日韩久久免费影院| 国产成人精品免费午夜app| 久久精品国产亚洲av高清漫画 | 国产精品久久久久久久久免费| 久久精品国产第一区二区三区| 久久99热成人精品国产| 久久精品99久久香蕉国产| 久久久久国产成人精品| 久久无码专区国产精品s| 久久综合精品不卡一区二区| 久热这里只精品99国产6_99| 天天爽夜夜爽夜夜爽精品视频| 日韩综合在线观看| 国产av一区最新精品| 久久精品视频亚洲| 国产精品成人观看视频国产奇米| 国内精品久久久久影院免费| 华人在线精品免费观看| 日本久久久精品中文字幕| 久久久这里有精品999|