我正在尝试将绑定写入C库。代码在C:
中调用如下#include <stdio.h>
#include <stdlib.h>
#include <libvirt/libvirt.h>
#include <string.h>
int main(int argc, char *argv[])
{
virConnectPtr conn;
conn = virConnectOpen("qemu:///system");
if (conn == NULL) {
fprintf(stderr, "Failed to open connection to qemu:///system\n");
return 1;
}
int nparams = 0;
virNodeCPUStats* params = malloc(sizeof(virNodeCPUStats) * nparams);
memset(params, 0, sizeof(virNodeCPUStats) * nparams);
int cpuNum = VIR_NODE_CPU_STATS_ALL_CPUS;
if (virNodeGetCPUStats(conn, cpuNum, NULL, &nparams, 0) == 0 &&
nparams != 0) {
if ((params = malloc(sizeof(virNodeCPUStats) * nparams)) == NULL)
goto error;
memset(params, 0, sizeof(virNodeCPUStats) * nparams);
if (virNodeGetCPUStats(conn, cpuNum, params, &nparams, 0))
goto error;
}
int err = virNodeGetCPUStats(conn, cpuNum, params, &nparams, 0);
printf("ret code %d\n", err);
printf("%d nparams\n", nparams);
int i = 0;
for(i = 0; i < nparams; i++){
printf("%s value\n", params[i].field);
printf("%llu value\n", params[i].value);
}
fflush(stdout);
error:
virConnectClose(conn);
return 0;
}
如您所见,您首先调用virNodeGetCPUStats来获取nparams(它在linux上返回4)然后再使用适当大小的virNodeCPUStats数组调用它,它将填充值并显示如下输出:< / p>
ret code 0
4 nparams
kernel value
991550000000 value
user value
4830840000000 value
idle value
199124620000000 value
iowait value
695120000000 value
PASS
在阅读了libvirt-go和ListAllStorageVolumes的代码后,我尝试了以下实现:
func (c *VirConnection) GetNodeCPUStats(flags C.uint) ([]VirNodeCPUStats, error) {
var nparams C.int
var params *C.virNodeCPUStatsPtr
var cpuNum C.int = -1 // change with cVIR_NODE_CPU_STATS_ALL_CPUS
var stats []VirNodeCPUStats
if C.virNodeGetCPUStats(c.ptr, cpuNum, nil, &nparams, 0) == 0 {
retcode := C.virNodeGetCPUStats(c.ptr, cpuNum, (*C.virNodeCPUStats)(unsafe.Pointer(¶ms)), &nparams, C.uint(0))
fmt.Println("D> Retcode: ", retcode) --> outputs 0, okay
}
fmt.Println("D> params: ", params)
header := reflect.SliceHeader{
Data: uintptr(unsafe.Pointer(params)),
Len: 4,
Cap: 4,
}
slice := *(*[]C.virNodeCPUStatsPtr)(unsafe.Pointer(&header))
for _, ptr := range slice {
stats = append(stats, VirNodeCPUStats{ptr}) //add for first
}
C.free(unsafe.Pointer(params))
return stats, nil
}
但是,它会出现以下错误:
D> params initial: <nil>
D> Successful: virNodeGetCPUStats
D> nparams: 4
D> ret code: 0
D> params: (*libvirt._Ctype_virNodeCPUStatsPtr)(0x6c656e72656b)
D> Header Data: 119182900487531
D> before slice
D> before for
unexpected fault address 0x6c656e72656b
fatal error: fault
[signal 0xb code=0x1 addr=0x6c656e72656b pc=0x4c0c04]
goroutine 87 [running]:
runtime.throw(0x613078, 0x5)
/usr/local/go/src/runtime/panic.go:547 +0x90 fp=0xc820053c80 sp=0xc820053c68
runtime.sigpanic()
/usr/local/go/src/runtime/sigpanic_unix.go:27 +0x2ab fp=0xc820053cd0 sp=0xc820053c80
github.com/rgbkrk/libvirt-go.(*VirConnection).GetNodeCPUStats(0xc820053ef0, 0x0, 0x0, 0x0, 0x0)
/home/tugba/go/src/github.com/rgbkrk/libvirt-go/libvirt.go:879 +0xa84 fp=0xc820053ec0 sp=0xc820053cd0
github.com/rgbkrk/libvirt-go.TestGetCPUStats(0xc8200beea0)
/home/tugba/go/src/github.com/rgbkrk/libvirt-go/libvirt_test.go:833 +0x66 fp=0xc820053f58 sp=0xc820053ec0
testing.tRunner(0xc8200beea0, 0x91acf8)
/usr/local/go/src/testing/testing.go:473 +0x98 fp=0xc820053f90 sp=0xc820053f58
runtime.goexit()
/usr/local/go/src/runtime/asm_amd64.s:1998 +0x1 fp=0xc820053f98 sp=0xc820053f90
created by testing.RunTests
/usr/local/go/src/testing/testing.go:582 +0x892
我没有正确切割C数组吗?到底是怎么回事?什么是意外故障,它怎么能在一个地址?这是否意味着我正在使用我不应该的记忆?