GoLang / CGO:在Go中调用Mach API的host_statistics()时出现问题

huangapple go评论67阅读模式
英文:

GoLang / CGO: Problems calling Mach API host_statistics() from Go

问题

我使用以下的C代码片段来获取OS X上的CPU负载:

#include <mach/message.h>
#include <mach/mach_host.h>
#include <mach/host_info.h>

[...]

mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
kern_return_t error;
host_cpu_load_info_data_t r_load;

mach_port_t host_port = mach_host_self();
error = host_statistics(host_port, HOST_CPU_LOAD_INFO, (host_info_t)&r_load, &count);

我尝试在阅读了cgo教程后将这段代码移植到Go语言中,结果的代码如下:

package main

/*
#include <stdlib.h>
#include <mach/message.h>
#include <mach/mach_host.h>
#include <mach/host_info.h>
*/
import "C"

func main() {
    var err C.kern_return_t
    var host_info_out C.host_info_t
    var host_port C.mach_port_t = C.mach_host_self()

    count := C.mach_msg_type_number_t(C.HOST_CPU_LOAD_INFO_COUNT)

    err = C.host_statistics(C.host_t(host_port), C.HOST_CPU_LOAD_INFO, &host_info_out, &count)
}

然而,当我尝试构建这段代码时,我得到了以下错误信息:

go build cputimes.go
# command-line-arguments
cputimes.go:33: cannot use &host_info_out (type *_Ctype_host_info_t) as type *_Ctype_integer_t in function argument

我不明白为什么cgo会抱怨类型。host_statistics()的签名在mach头文件中定义如下:

kern_return_t host_statistics
(
    host_t host_priv,
    host_flavor_t flavor,
    host_info_t host_info_out,
    mach_msg_type_number_t *host_info_outCnt
);
英文:

I use the following C code fragment to get the CPU load on OS X:

    #include &lt;mach/message.h&gt; 
    #include &lt;mach/mach_host.h&gt;
    #include &lt;mach/host_info.h&gt;

    [...]

    mach_msg_type_number_t  count = HOST_CPU_LOAD_INFO_COUNT;
    kern_return_t error;
    host_cpu_load_info_data_t r_load;

    mach_port_t host_port = mach_host_self();
    error = host_statistics(host_port, HOST_CPU_LOAD_INFO, (host_info_t)&amp;r_load, &amp;count);

I have tried to port this piece of code to Go after reading the cgo tutorial. The resulting code looks like this:

package main

/*
#include &lt;stdlib.h&gt;
#include &lt;mach/message.h&gt;
#include &lt;mach/mach_host.h&gt;
#include &lt;mach/host_info.h&gt;
*/
import &quot;C&quot;

func main() {
	var err C.kern_return_t
	var host_info_out C.host_info_t
	var host_port C.mach_port_t = C.mach_host_self()
    
	count := C.mach_msg_type_number_t(C.HOST_CPU_LOAD_INFO_COUNT)

	err = C.host_statistics(C.host_t(host_port), C.HOST_CPU_LOAD_INFO, &amp;host_info_out, &amp;count)
}

However, when I try to build the code, I end up with the following error message

go build cputimes.go 
# command-line-arguments
cputimes.go:33: cannot use &amp;host_info_out (type *_Ctype_host_info_t) as type *_Ctype_integer_t in function argument

I do not udnerstand why cgo complains about the type. The signature of host_statistics() is defined in the mach headers as:

 kern_return_t host_statistics
 (
      host_t host_priv,
      host_flavor_t flavor,
      host_info_t host_info_out,
      mach_msg_type_number_t *host_info_outCnt
 );

答案1

得分: 1

函数原型表明host_statistics的第三个参数是一个host_info_t变量,而你在示例程序中传递的是一个指向host_info_t变量的指针。

查看mach/host_info.h头文件,我们可以看到host_info_t是一个指针类型:

typedef integer_t	*host_info_t;		/* varying array of int. */

这解释了为什么你会收到关于integer_t类型不匹配的错误消息。

你的Go代码在处理该参数时似乎与C代码不太相等。你可能想要像这样做一些修改:

...
var r_load C.host_cpu_load_info_data_t
...
err = C.host_statistics(C.host_t(host_port), C.HOST_CPU_LOAD_INFO, C.host_info_t(unsafe.Pointer(&amp;r_load)), &amp;count)
...

(你需要使用unsafe包在不兼容的指针类型之间进行转换)。

英文:

The function prototype says that the third argument to host_statistics is a host_info_t variable, while you are passing a pointer to a host_info_t variable in your sample program.

Looking at the mach/host_info.h header file, we can see that host_info_t is a pointer type:

typedef integer_t	*host_info_t;		/* varying array of int. */

That explains why you got the error message about a type mismatch with integer_t.

Your Go code doesn't really look equivalent to the C code when handling that argument. You probably want something more like this:

...
var r_load C.host_cpu_load_info_data_t
...
err = C.host_statistics(C.host_t(host_port), C.HOST_CPU_LOAD_INFO, C.host_info_t(unsafe.Pointer(&amp;r_load)), &amp;count)
...

(you need to use the unsafe package to cast between the incompatible pointer types).

huangapple
  • 本文由 发表于 2013年10月2日 02:14:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/19123059.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定