How to cast bytes to struct(c struct) in go?

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

How to cast bytes to struct(c struct) in go?

问题

package main

/*
#define _GNU_SOURCE 1
#include <stdio.h>
#include <stdlib.h>
#include <utmpx.h>
#include <fcntl.h>
#include <unistd.h>

char *path_utmpx = _PATH_UTMPX;

typedef struct utmpx utmpx;
*/
import "C"
import (
	"fmt"
	"io/ioutil"
)

type Record C.utmpx

func main() {

	path := C.GoString(C.path_utmpx)

	content, err := ioutil.ReadFile(path)
	handleError(err)

	var records []Record

	// 现在我们有了字节(content)和结构体(Record/C.utmpx)
	// 我们如何将字节转换为结构体?
}

func handleError(err error) {
	if err != nil {
		panic("bad")
	}
}

我正在尝试将content读入Record中。
我已经提出了一些相关的问题。

https://stackoverflow.com/q/44036358/5819540

https://stackoverflow.com/q/45300938/5819540

我已经阅读了一些文章和帖子,但仍然无法找到解决方法。

英文:
package main

/*
#define _GNU_SOURCE 1
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;utmpx.h&gt;
#include &lt;fcntl.h&gt;
#include &lt;unistd.h&gt;

char *path_utmpx = _PATH_UTMPX;

typedef struct utmpx utmpx;
*/
import &quot;C&quot;
import (
  &quot;fmt&quot;
  &quot;io/ioutil&quot;
)

type Record C.utmpx

func main() {

  path := C.GoString(C.path_utmpx)

  content, err := ioutil.ReadFile(path)
  handleError(err)

  var records []Record

  // now we have the bytes(content), the struct(Record/C.utmpx)
  // how can I cast bytes to struct ?
}

func handleError(err error) {
  if err != nil {
    panic(&quot;bad&quot;)
  }
}

I'm trying to read content into Record
I have asked a few related questions.

https://stackoverflow.com/q/44036358/5819540

https://stackoverflow.com/q/45300938/5819540

I have read some articles and posts but still cannot figure out a way to do this.

答案1

得分: 1

我认为你的方法不对。如果你想使用C库,你应该使用C库来读取文件。

不要仅仅为了有结构定义而使用cgo,你应该自己在Go中创建这些结构。然后,你可以编写适当的编组/解组代码来从原始字节中读取。

快速搜索显示,有人已经完成了将相关的C库转换为Go所需的工作。请参考utmp存储库

以下是如何使用的简短示例:

package main

import (
	"bytes"
	"fmt"
	"log"

	"github.com/ericlagergren/go-gnulib/utmp"
)

func handleError(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func byteToStr(b []byte) string {
	i := bytes.IndexByte(b, 0)
	if i == -1 {
		i = len(b)
	}
	return string(b[:i])
}

func main() {
	list, err := utmp.ReadUtmp(utmp.UtmpxFile, 0)
	handleError(err)
	for _, u := range list {
		fmt.Println(byteToStr(u.User[:]))
	}
}

你可以查看utmp包的GoDoc获取更多信息。

英文:

I think you're going about this the wrong way. If you were wanting to use the C library, you would use the C library to read the file.

Don't use cgo purely to have struct definitions, you should create these in Go yourself. You could then write the appropriate marshal / unmarshal code to read from the raw bytes.

A quick Google shows that someone has already done the work required to convert a look of the relevant C library to Go. See the utmp repository.

A short example of how this could be used is:

package main

import (
	&quot;bytes&quot;
	&quot;fmt&quot;
	&quot;log&quot;

	&quot;github.com/ericlagergren/go-gnulib/utmp&quot;
)

func handleError(err error) {
	if err != nil {
		log.Fatal(err)
	}
}

func byteToStr(b []byte) string {
	i := bytes.IndexByte(b, 0)
	if i == -1 {
		i = len(b)
	}
	return string(b[:i])
}

func main() {
	list, err := utmp.ReadUtmp(utmp.UtmpxFile, 0)
	handleError(err)
	for _, u := range list {
		fmt.Println(byteToStr(u.User[:]))
	}
} 

You can view the GoDoc for the utmp package for more information.

huangapple
  • 本文由 发表于 2017年7月26日 14:03:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/45318603.html
匿名

发表评论

匿名网友

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

确定