golang中采用cgo调用c++的so

golang中采用cgo调用c++的so,第1张

golang中采用cgo调用c++的so
背景

基于arm平台的生鲜识别系统,采用了go语言做为边缘端业务逻辑语言,其中调用识别模型so库来实现推理(so调用jetson nano cuda)将返回结果进行业务处理。在生鲜场景已运用成熟,当向零食识别集成时,若采用单一模型,也就是在原有模型的基础上,增加零食数据训练出来的大模型,生鲜的识别将受影响,所以,诞生了生鲜与零食两个模型的想法。

技术实现

go调用c++的so,需要通过c来调用,网上有关于cgo的使用方法,介绍篇幅非常有限,特别是对so的调用。最难的是在于复杂类型的转换,golang与c++中的类型,哪怕是常见的int、char、指针等,因两种语言定义不同,为so的集成增添了难度,经过一段时间的摸索,终于将功能实现。

那么go中如何调用so库呢?C++写的libxxxx.so库,golang中集成时,需定义出so中函数的头文件,在go文件中引用,并描述so的名称,就可以调用so中的函数了。接下来,我们由简入深吧!

golang中直接调用c
// go的源代码中直接声明C代码,比较简单的应用情况 可以直接使用这种方法 C代码直接写在 go 代码的注释中 注释之后紧跟import "C" 通过C.xx来引用C的结构和函数

package main

/*
#include 
#include 

typedef struct {
    int id;
}ctx;

ctx *createCtx(int id) {
    ctx *obj = (ctx *)malloc(sizeof(ctx));
    obj->id = id;
    return obj;
}
*/
import "C"
import (
    "fmt"
    "sync"
)

func main() {
    var ctx *C.ctx = C.createCtx(100)
    fmt.Printf("id : %d\n", ctx.id)
}

参考:https://www.codercto.com/a/39274.html,其中也有直接调用c++的示例

golang中调用so库 - 定义头文件,描述so中的函数
#ifndef F1_INFERENCE_API_H
#define F1_INFERENCE_API_H

#ifdef __cplusplus
extern "C" {
#endif

char* get_version();
int process(const unsigned char *data, int length, int num, float *result);

#ifdef __cplusplus
}
#endif
#endif //F1_INFERENCE_API_H
- 将libxxxx.so放到指定的目录中
cp libxxxx.so ~/.local/lib/
- golang中的调用 - 编译go代码
export GODEBUG=cgocheck=0
export LD_LIBRARY_PATH=:/home/f1/.local/lib;
export LIBRARY_PATH=:/home/f1/.local/lib; 
CGO_ENABLED=1 GOOS=linux go build main.go
golang与c++中类型转换
- c++中的long long类型
    Golang 中采用C.longlong(t)来转换

- c++中的float数组
    var scores [2]float32
    scores[0] = 0.8
    scores[1] = 0.9
    // 调用:入参
    C.test_float((*C.float)(unsafe.Pointer(&scores[0])))

- c++中的字符串
    Golang 中对应的类型与赋值
    var path *C.char
    path = C.CString("/home/f1/ailog.log")

- c++中的字符数组
    Golang 中对应的类型与赋值
    var names [8]*C.char
    names[0] = C.CString("苹果")
    names[1] = C.CString("大白菜")
    输入参数时需转换为**char类型
    C.test_chararray((**C.char)(unsafe.Pointer(&sku[0])))

- c++中**char转golang切片[]string
    //char** 转化成 []string
    list := C.getStringArray()
    var str []string
    var pbuf []*C.char
    header := (*reflect.SliceHeader)(unsafe.Pointer(&pbuf))
    header.Cap = 3
    header.Len = 3
    header.Data = uintptr(unsafe.Pointer(list))
    for _, i := range pbuf {
        str = append(str, C.GoString(i))
    }
    fmt.Println(str)

    //[]string 转化成 char**
    box := []string{"xing", "jack", "john"}
    var buf []*C.char
    for i, _ := range box {
        buf = append(buf, (*C.char)(unsafe.Pointer(C.CString(box[i]))))
    }
    box2 := (**C.char)(unsafe.Pointer(&buf[0]))

    参考:https://www.zhihu.com/question/27168644

 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/995916.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存