Marshalling C objects that cannot be accessed from Go - go

There are some C objects like unions, structs that contain bitfields and structs whose alignment differs from Go's ABI, that cannot be accessed from Go. Some of these structures cannot be changed to be accessible from Go code as they are part of the API of an existing library.
To marshall such objects into Go structures we thus cannot really use Go code. Instead w have to write the marshalling code in C. This works fine but I have not found a feasible way to define C functions that operate on types defined in Go code. Right now I am defining the data types I am marshalling into on the C side and use these data types in my Go code.
This is really nasty if I want to expose the marshalled types as an API in my Go code, as I cannot expose a C type as a part of my package interface. My current approach involves remarshalling the already marshalled object into a type that is defined in Go code.
Is there a more elegant way to do what I want to do, i.e. marshalling C structs that cannot be accessed from Go code into data types defined in Go code?
As requested in the comment section, here is a collection of C objects that cannot be accessed from Go.
#include <complex.h>
#include <stdbool.h>
union foo {
int i;
float f;
};
struct bar {
bool x:1;
unsigned int y:3;
unsigned int z:4;
};
struct baz {
float f;
complex float c;
};
#pragma pack 1
struct quux {
char c;
short s;
int i;
};

The standard package encoding/binary can be used for manipulating raw C structs.
You can extend Read and Write functions to support custom types :
func Read(r io.Reader, order binary.ByteOrder, data interface{}) error {
switch data := data.(type) {
case *foo:
return readFoo(r, order, data)
// (...)
default:
return binary.Read(r, order, data)
}
}
func Write(w io.Writer, order binary.ByteOrder, data interface{}) error {
switch data := data.(type) {
case foo:
return writeFoo(r, order, data)
// (...)
default:
return binary.Write(r, order, data)
}
}
Use a struct containing all the union's fields and use application context to decide which value to encode into the C union.
type foo struct {
is_i bool
i int32
f float32
}
// Read a foo from r into data
func readFoo(r io.Reader, order binary.ByteOrder, data *foo) error {
b := make([]byte, 4)
if _, err := io.ReadFull(r, b); err != nil {
return err
}
*data = foo{
i: int32(order.PutUint32(b)),
f: float32(order.PutUint32(b)),
}
return nil
}
// Write a foo from data into w
func writeFoo(w io.Writer, order binary.ByteOrder, data foo) error {
b := make([]byte, 4)
if data.is_i {
order.PutUint32(b, uint32(data.i))
} else {
order.PutUint32(b, uint32(data.f))
}
_, err := w.Write(b)
return err
}
(Alternatively, using getters and setters: http://pastebin.com/H1QW5AFb)
Use bitwise operations to marshal bitfields
type bar struct {
x bool
y uint
z uint
}
// Read a bar from r into data
func readBar(r io.Reader, order binary.ByteOrder, data *foo) error {
b := make([]byte, 1)
if _, err := io.ReadFull(r, b); err != nil {
return err
}
// Read from bitfield
*data = bar{
x: bool(b[0] >> 7), // bool x:1;
y: uint((b[0] & 0x70) >> 3), // unsigned int y:3;
z: uint(b[0] & 0x0f), // unsigned int z:4;
}
return nil
}
// Write a bar from data into w
func writeBar(w io.Writer, order binary.ByteOrder, data bar) error {
b := make([]byte, 1)
var x uint8
if data.x {
x = 1
}
// Create bitfield
b[0] = (x & 0x01 << 7) & // bool x:1;
(uint8(data.y) & 0x03 << 4) & // unsigned int y:3;
(uint8(data.z) & 0x04) // unsigned int z:4;
_, err := w.Write(b)
return err
}
The serialized form of baz depends on the compiler's internal definition of complex.
When using encoding.binary, fields have a 1-byte alignement so quux can be marshaled directly.

Related

go generics: processing different struct types with same data member types [duplicate]

This question already has answers here:
How can I access a struct field with generics (type T has no field or method)?
(1 answer)
Generic function to work on different structs with common members from external package?
(1 answer)
Closed 3 months ago.
There are two struct types, Foo and Bar, with an int data member val. I am trying to write a generic function that can handle both types. I tried the following and this did not work.
package main
import "fmt"
type Foo struct {
val int
}
type Bar struct {
val int
}
func Add[T any](slice []T) int {
var sum int
for _, elem := range slice {
sum += elem.val
}
return sum
}
func Test() {
f1 := Foo{val: 2}
f2 := Foo{val: 2}
fslice := []Foo{f1, f2}
fsum := Add(fslice)
fmt.Printf("fsum = %d\n", fsum)
b1 := Bar{val: 3}
b2 := Bar{val: 3}
bslice := []Bar{b1, b2}
bsum := Add(bslice)
fmt.Printf("bsum = %d\n", bsum)
}
func main() {
Test()
}
The compiler throws the following error.
$ go run generics1.go
# command-line-arguments
./generics1.go:16:15: elem.val undefined (type T has no field or method val)
Go playground link: https://go.dev/play/p/mdOMH3xuwu7
What could be a possible way to approach this?
Per golang 1.18 release note
The Go compiler does not support accessing a struct field x.f where x is of type parameter type even if all types in the type parameter's type set have a field f. We may remove this restriction in a future release.
You could define one GetVal() interface method to retrieve the val, and use this method as part of type constraint of generic.
Sample codes
type Foo struct {
val int
}
func (f Foo) GetVal() int {
return f.val
}
type Bar struct {
val int
}
func (b Bar) GetVal() int {
return b.val
}
type MyType interface {
Foo | Bar
GetVal() int
}
func Add[T MyType](slice []T) int {
var sum int
for _, elem := range slice {
sum += elem.GetVal()
}
return sum
}
https://go.dev/play/p/0eJZpqy7q8f

How do I get at the contents of a private reflect.Value in go?

I'm trying to make a general purpose debug printer for complex data types because %v has a tendency to just print pointer values rather than what they point at. I've got it working with everything up until I have to deal with structs containing reflect.Value fields.
The following demo code runs without error: (https://play.golang.org/p/qvdRKc40R8k)
package main
import (
"fmt"
"reflect"
)
type MyStruct struct {
i int
R reflect.Value
}
func printContents(value interface{}) {
// Omitted: check if value is actually a struct
rv := reflect.ValueOf(value)
for i := 0; i < rv.NumField(); i++ {
fmt.Printf("%v: ", rv.Type().Field(i).Name)
field := rv.Field(i)
switch field.Kind() {
case reflect.Int:
fmt.Printf("%v", field.Int())
case reflect.Struct:
// Omitted: check if field is actually a reflect.Value to an int
fmt.Printf("reflect.Value(%v)", field.Interface().(reflect.Value).Int())
}
fmt.Printf("\n")
}
}
func main() {
printContents(MyStruct{123, reflect.ValueOf(456)})
}
This prints:
i: 123
R: reflect.Value(456)
However, if I change MyStruct's R field name to r, it fails:
panic: reflect.Value.Interface: cannot return value obtained from unexported field or method
Of course, it's rightly failing because this would otherwise be a way to get an unexported field into proper goland, which is a no-no.
But this leaves me in a quandry: How can I gain access to whatever the unexported reflect.Value refers to without using Interface() so that I can walk its contents and print? I've looked through the reflect documentation and haven't found anything that looks helpful...
After some digging, I've found a solution:
The only way to get at the inner reflect.Value is to call Interface() and type assert it, but this will panic if called on an unexported field. The only way around this is to use the unsafe package to clear the read-only flag so that the Interface() method will think it's exported when it's not (basically, we subvert the type system):
type flag uintptr // reflect/value.go:flag
type flagROTester struct {
A int
a int // reflect/value.go:flagStickyRO
int // reflect/value.go:flagEmbedRO
// Note: flagRO = flagStickyRO | flagEmbedRO
}
var flagOffset uintptr
var maskFlagRO flag
var hasExpectedReflectStruct bool
func initUnsafe() {
if field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag"); ok {
flagOffset = field.Offset
} else {
log.Println("go-describe: exposeInterface() is disabled because the " +
"reflect.Value struct no longer has a flag field. Please open an " +
"issue at https://github.com/kstenerud/go-describe/issues")
hasExpectedReflectStruct = false
return
}
rv := reflect.ValueOf(flagROTester{})
getFlag := func(v reflect.Value, name string) flag {
return flag(reflect.ValueOf(v.FieldByName(name)).FieldByName("flag").Uint())
}
flagRO := (getFlag(rv, "a") | getFlag(rv, "int")) ^ getFlag(rv, "A")
maskFlagRO = ^flagRO
if flagRO == 0 {
log.Println("go-describe: exposeInterface() is disabled because the " +
"reflect flag type no longer has a flagEmbedRO or flagStickyRO bit. " +
"Please open an issue at https://github.com/kstenerud/go-describe/issues")
hasExpectedReflectStruct = false
return
}
hasExpectedReflectStruct = true
}
func canExposeInterface() bool {
return hasExpectedReflectStruct
}
func exposeInterface(v reflect.Value) interface{} {
pFlag := (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + flagOffset))
*pFlag &= maskFlagRO
return v.Interface()
}
There are caveats, in that unsafe isn't allowed or desirable in all environments, not to mention that subverting the type system is rarely the right thing to do. It's recommended that you make such code conditional on build tags, and include a safe alternative.

Is it possible to define an anonymous interface implementation in Go?

Consider some given interface and a function of an imaginary library that uses it like
// Binary and Ternary operation on ints
type NumOp interface {
Binary(int, int) int
Ternary(int, int, int) int
}
func RandomNumOp(op NumOp) {
var (
a = rand.Intn(100) - 50
b = rand.Intn(100) - 50
c = rand.Intn(100) - 50
)
fmt.Printf("%d <op> %d = %d\n", a, b, op.Binary(a,b))
fmt.Printf("%d <op> %d <op> %d = %d\n", a, b, c, op.Ternary(a,b,c))
}
A possible type implementing that interface could be
// MyAdd defines additions on 2 or 3 int variables
type MyAdd struct {}
func (MyAdd) Binary(a, b int) int {return a + b }
func (MyAdd) Ternary(a, b, c int) int {return a + b + c }
I am dealing with many different interfaces defining a few functions that in some cases need to be implemented using functions mostly working as NOP-like operations, do not rely on any struct member and are only used in a single position in the project (no reusability needed).
Is there a simpler (less verbose) way in Go to define a (preferably) anonymous implementation of an interface using anonymous functions, just like (pseudo code, I know it's not working that way):
RandomNumOp({
Binary: func(a,b int) int { return a+b},
Ternary: func(a,b,c int) int {return a+b+c},
})
If implementation must work
If the value implementing the interface must work (e.g. its methods must be callable without panic), then you can't do it.
Method declarations must be at the top level (file level). And to implement an interface that has more than 0 methods, that requires to have the method declarations somewhere.
Sure, you can use a struct and embed an existing implementation, but then again, it requires to already have an existing implementation, whose methods must already be defined "somewhere": at the file level.
If you need a "dummy" but workable implementation, them use / pass any implementation, e.g. a value of your MyAdd type. If you want to stress that the implementation doesn't matter, then create a dummy implementation whose name indicates that:
type DummyOp struct{}
func (DummyOp) Binary(_, _ int) int { return 0 }
func (DummyOp) Ternary(_, _, _ int) int { return 0 }
If you need to supply implementation for some of the methods dynamically, you may create a delegator struct type which holds functions for the methods, and the actual methods check if the respective function is set, in which case it is called, else nothing will be done.
This is how it could look like:
type CustomOp struct {
binary func(int, int) int
ternary func(int, int, int) int
}
func (cop CustomOp) Binary(a, b int) int {
if cop.binary != nil {
return cop.binary(a, b)
}
return 0
}
func (cop CustomOp) Ternary(a, b, c int) int {
if cop.ternary != nil {
return cop.ternary(a, b, c)
}
return 0
}
When using it, you have the freedom to only supply a subset of functions, the rest will be a no-op:
RandomNumOp(CustomOp{
binary: func(a, b int) int { return a + b },
})
If implementation is not required to work
If you only need a value that implements an interface but you don't require its methods to be "callable" (to not panic if called), you may simply use an anonymous struct literal, embedding the interface type:
var op NumOp = struct{ NumOp }{}

How to dynamically create a struct with one less property?

Is there a way to copy a generic struct (i.e. a struct whose property names are unknown) and skip a single, known property?
Here is what I know:
The parameter to my function--I will call the parameter myData-- is of type interface{}.
myData is a struct.
myData has a known property path.
myData has anywhere from 0 to 6 or so other properties, none of which are known a priori.
Once I remove that path property, then the “leftover” is one of say 30 possible struct types.
So I want to strip path out of myData (or more accurately make a copy that omits path) so that various bits of generated code that try to coerce the struct to one of its possible types will be able to succeed.
I have found examples of copying a struct by reflection, but they typically create an empty struct of the same underlying type, then fill it in. So is it even possible to delete a property as I have outlined...?
You can use reflect.StructOf to dynamically create structs from a list of fields.
package main
import (
"fmt"
"reflect"
)
type A struct {
Foo string
Bar int
Baz bool // to be skipped
}
type B struct {
Foo string
Bar int
}
func main() {
av := reflect.ValueOf(A{"hello", 123, true})
fields := make([]reflect.StructField, 0)
values := make([]reflect.Value, 0)
for i := 0; i < av.NumField(); i++ {
f := av.Type().Field(i)
if f.Name != "Baz" {
fields = append(fields, f)
values = append(values, av.Field(i))
}
}
typ := reflect.StructOf(fields)
val := reflect.New(typ).Elem()
for i := 0; i < len(fields); i++ {
val.Field(i).Set(values[i])
}
btyp := reflect.TypeOf(B{})
bval := val.Convert(btyp)
b, ok := bval.Interface().(B)
fmt.Println(b, ok)
}

C char name[8] to GoLang Name [8]byte

I've got a C function that fills a C struct:
typedef struct {
char name[8];
}
I need to copy data into Go lang struct that has the same content:
type sData struct {
Name [8]byte
}
The structure has parameters of multiple sizes: 4, 12, 32 so it would be nice to have a function that deals with more than just one size.
thanks
To make this a little more generic, you can decompose the C char array to a *C.char, then use unsafe.Pointer to cast it back to an array.
func charToBytes(dest []byte, src *C.char) {
n := len(dest)
copy(dest, (*(*[1024]byte)(unsafe.Pointer(src)))[:n:n])
}
Or maybe a little easier
func charToBytes(src *C.char, sz int) []byte {
dest := make([]byte, sz)
copy(dest, (*(*[1024]byte)(unsafe.Pointer(src)))[:sz:sz])
return dest
}

Resources