目录
- 思路
 - C ++ 相关文件
 - 目录列表
 - 源码示例
 - some.h
 - some_wrapper.h
 - some_wrapper.cpp
 - 将 C++ 库包装成 C 库
 - Golang CGO 调用 C 库
 - 参考
 - 总结
 
思路
将 C++ 库包装成 C 库 -> golang 通过 cgo 调用 C 库
C ++ 相关文件
目录列表
- include/
- some.h C++ 库头文件
 - some_wrapper.h <= 用于将 C++ 库包装成 C 库的头文件
 
 - lib/
- libsome.a C++ 库
 
 - src/
- some_wrapper.cpp <= 用于将 C++ 库包装成 C 库的源码文件
 
 
源码示例
some.h
#ifndef SOME_H
#define SOME_H
#include <string>
#include <utility>
#include <vector>
namespace Some {
	struct DeviceInfo {
	  std::string id;
	};
	std::vector<std::pair<std::string, std::string>> Generate(const DeviceInfo& device);
}
#endif  // SOME_H
some_wrapper.h
#ifndef SOME_WRAPPER_H
#define SOME_WRAPPER_H
	#ifdef __cplusplus
	extern "C" {
	#endif
	    struct some_item {
	        char version[8];
	        char value[32];
	    };
	
	    struct some_result {
	        struct some_item data[1];
	        int size;
	    };
	
	    int generate(struct some_result* result, char* id);
	
	#ifdef __cplusplus
	}
	#endif
#endif // SOME_WRAPPER_H
some_wrapper.cpp
#include <string.h>
#include "some.h"
#include "some_wrapper.h"
#ifdef __cplusplus
extern "C" {
#endif
    int generate(struct some_result* result, char* id) {
        Some::DeviceInfo deviceInfo;
        deviceInfo.id = id;
        auto v = Some::Generate(deviceInfo);
        strcpy(result->data[0].version, v.first.data());
        strcpy(result->data[0].value, v.second.data());
        result->size = 1;
        return 0;
    }
#ifdef __cplusplus
}
#endif
将 C++ 库包装成 C 库
# 编译生成 src/some_wrapper.o 临时目标文件 g++ -c -Iinclude src/some_wrapper.cpp -o src/some_wrapper.o # 生成静态库 lib/libsomewrapper.a ar -cr lib/libsomewrapper.a src/some_wrapper.o # 删除临时目标文件 rm -rf src/some_wrapper.o
Golang CGO 调用 C 库
package main
// #cgo CFLAGS: -I  ${SRCDIR}/include
// #cgo LDFLAGS: -L ${SRCDIR}/lib -lsomewrapper -lsome -lstdc++
// #include <stdlib.h>
// #include "some_wrapper.h"
import "C"
import (
	"unsafe"
)
type DeviceInfo struct {
	ID string `json:"id"`
}
func main() {
	di := DeviceInfo{
		ID: "123456",
     }
	cID:= C.CString(di.ID)
	defer C.free(unsafe.Pointer(cID))
	some := &C.struct_some_result{}
	C.generate(some, cId)
	if len(some.data) > 0 {
		item := some.data[0]
		version := C.GoStringN(&(item.version[0]), 8)
		value := C.GoStringN(&(item.value[0]), 32)
	
		result := make(map[string]string, someSize)
		result[version] = value
	
		someSize := int(some.size)
	
		fmt.Println(result, someSize)
	}
}
# 编译 go 文件 go install -v # 运行 $GOPATH/bin/demo
参考
- https://pkg.go.dev/cmd/cgo
 - https://stackoverflow.com/questions/41811563/do-i-have-to-free-structs-created-with-cgo
 
总结
	声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
		
评论(0)