GZ Xue GZ Xue - 3 years ago 148
C Question

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

// 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("bad")
}
}


I'm trying to read
content
into
Record

I have asked a few related questions.

Cannot access c variables in cgo

Can not read utmpx file in go

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

Answer Source

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 (
    "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[:]))
    }
} 

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

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download