c - C调用Go导出函数
问题描述
我想将一个数组返回给 C 调用者,就像下面一样,该怎么做?
//export EtcdGetAllNodes
func EtcdGetAllNodes()[]uint32 {
a := []uint32{1,2,3}
return a
}
此函数EtcdGetAllNodes
将尝试从 etcd 获取带有特定键前缀的值,它将返回多个值。如何将这些值返回给 C 调用者?
解决方案
C 代码调用的 Go 函数可能不会返回 Go 指针(这意味着它可能不会返回字符串、切片、通道等)。C 代码调用的 Go 函数可以将 C 指针作为参数,它可以通过这些指针存储非指针或 C 指针数据,但它可能不会在 C 指针指向的内存中存储 Go 指针。C 代码调用的 Go 函数可以将 Go 指针作为参数,但它必须保留其指向的 Go 内存不包含任何 Go 指针的属性。
我想将一个数组返回给 C 调用者。
//export EtcdGetAllNodes func EtcdGetAllNodes() []uint32 { a := []uint32{1, 2, 3} return a }
C 代码调用的 Go 函数可能不会返回 Go 指针(这意味着它可能不会返回切片)。
有很多可能的解决方案:命令 cgo。
例如,这是一个简单的解决方案:
输出:
$ go build -buildmode=c-archive -o cmem.a cmem.go
$ gcc -pthread -o cmem cmem.c cmem.a
$ ./cmem
-- EtcdGetAllNodes --
nodes: 3
node 0: 1
node 1: 2
node 2: 3
$ echo $?
0
$
cmem.go
:
package main
/*
#include <stdint.h>
#include <stdlib.h>
*/
import "C"
import "unsafe"
// toC: Go slice to C array
// c[0] is the number of elements,
// c[1] through c[c[0]] are the elements.
// When no longer in use, free the C array.
func toC(a []uint32) *C.uint32_t {
// C array
ca := (*C.uint32_t)(C.calloc(C.size_t(1+len(a)), C.sizeof_uint32_t))
// Go slice of C array
ga := (*[1 << 30]uint32)(unsafe.Pointer(ca))[: 1+len(a) : 1+len(a)]
// number of elements
ga[0] = uint32(len(a))
// elements
for i, e := range a {
ga[1+i] = e
}
return ca
}
//export EtcdGetAllNodes
// EtcdGetAllNodes: return all nodes as a C array.
// nodes[0] is the number of node elements.
// nodes[1] through nodes[nodes[0]] are the node elements.
// When no longer in use, free the nodes array.
func EtcdGetAllNodes() *C.uint32_t {
// TODO: code to get all etcd nodes
a := []uint32{1, 2, 3}
// nodes as a C array
return toC(a)
}
func main() {}
cmem.c
:
#include "cmem.h"
#include <stdint.h>
#include <stdio.h>
int main() {
printf("-- EtcdGetAllNodes --\n");
// nodes[0] is the number of node elements.
// nodes[1] through nodes[nodes[0]] are the node elements.
// When no longer in use, free the nodes array.
uint32_t *nodes = EtcdGetAllNodes();
if (!nodes) {
return 1;
}
printf("nodes: %d\n", *nodes);
for (uint32_t i = 1; i <= *nodes; i++) {
printf("node %d: %d\n", i-1,*(nodes+i));
}
free(nodes);
return 0;
}
推荐阅读
- python - 从关联实体结果到二维熊猫数据框的 Python sql 查询
- amazon-web-services - 错误 !S3 存储桶、Terraform AWS docker-compose 没有有效的凭证源
- c# - 显示登录屏幕并使用登录详细信息在 Azure Bot Framework 中验证 REST API
- python-3.x - for 循环内的 for 循环运行时间过长
- linux - 在 Linux 机器上使用 Apple 的 usdzconvert
- python - Azure 函数和 Blob 触发器超时
- html - 使用转换属性后如何对齐文本
- reactjs - onClick事件更改类名反应js
- javascript - PhotoeditorSDK - 如何实现导出功能
- python - 模拟和测试从 url 返回文本的函数