Create a C struct array in Go - go

I am trying to call a C lib from a Go program using CGo. I have the following C files that makes up the C lib. But, I get the following error" cgo parameter has Go pointer to Go pointer". I am struck with creating a C struct array in Go.
caller.h
enum c_callerIdType{
user,
certificate
}
typedef struct _c_callerid
{
c_callerIdType type,
char* value
}c_callerId;
typedef struct _c_requiredprops{
char* operationName,
CallerId* caller_id_set,
int caller_id_set_size
}c_requiredProps;
int log_caller_details(c_requiredProps);
caller.c
#include "caller.h"
int log_caller_details(c_requiredProps* rp){
printf("Operation name is %s", rp->operationName);
// printf the callerid details
return 1;
}
I created a Go wrapper around this C library as follows.
main.go
package main
// #include "caller.h"
// #include <stdlib.h>
import "C"
import "fmt"
type CallerId struct{
type string
value string
}
type RequiredProperties struct{
operationName string
callerIds []CallerId
}
// a helper function to call in to the C lib
func callCFunc() int{
var cRequiredProps C.c_requiredProps
var requiredProps RequiredProperties
var userCaller CallerId
var certCaller CallerId
// create user caller
userCaller.type = "user"
userCaller.value = "user1"
// create certificate caller
certCaller.type ="certificate"
certCaller.value = "service1.widgetcorp.com"
requiredProps.operationName = "UpdateWidget"
requiredProps.callerIds = []{userCaller,certCaller}
// convert from Go struct to C struct
var cOpName = C.CString(requiredProps.operationName)
defer C.free(unsafe.Pointer(cOpName))
cRequiredProps.operationName = cOpName
var cCallerIds = make([]C.c_callerId, 2)
for i,callerId := range requiredProps.callerIds{
var cTempCallerId C.c_callerId
cTempCallerId.type = C.c_callerIdType(callerId.type)
var cValue = C.CString(callerId.value)
cTempCallerId.value = cValue
defer C.free(unsafe.Pointer(cValue))
cCallerIds[i] = cTempCallerId
}
// this line throws error "CGo parameter has Go pointer to Go pointer" --> cRequiredProps.caller_id_set = (*C.c_requiredProps) (unsafe.Pointer(&cCallerIds[0]))
cRequiredProps.caller_id_set_size=2
return 1
}
func main() int{
fmt.PrintLn(callCFunc())
}
What am I doing wrong? How do I create an array of C structs inside Go and call a C function?

Related

Check for empty inline struct

Can an inline struct in Go be checked for emptiness?
The following example checks p, which is of type Person for emptiness.
It also defines the inline struct i. (How) can i be checked for emptiness?
package main
import (
"fmt"
)
type Person struct {
name string
}
func main() {
// Types can be checked for emptiness.
p := Person{}
if (p == Person{}) {
fmt.Println("Empty!")
}
// But: how to check for an empty inline struct?
// I.e. how to check, if i is empty?
var i struct {
value int
}
fmt.Println(i) // Required, or compiler will complain about unused 'i'.
}

interface{} convert to unsafe.Pointer problem

I am doing some test about unsafe.Pointer. Suppose TestFun is a common library function, so "Person" struct should not appear in this function
type Person struct {
Name string
}
func main() {
p := &Person{}
p.Name = "TestName"
TestFun(p)
}
func TestFun(val interface{}) {
// I want to convert interface{} to unsafe.Pointer
var pointer unsafe.Pointer
// This Line compile error
//pointer = unsafe.Pointer(val)
// This is ok, but "Person" appears. This function is a common function, "Person" should not appear
// pointer = unsafe.Pointer(val.(*Person))
println(pointer)
}
How could I do this ?
Instead of unsafe.Pointer(val), use unsafe.Pointer(&val). Because it accepts pointer.
package main
import (
"unsafe"
)
type Person struct {
Name string
}
func main() {
p := &Person{}
p.Name = "TestName"
TestFun(p)
}
func TestFun(val interface{}) {
// I want to convert interface{} to unsafe.Pointer
var pointer unsafe.Pointer
pointer = unsafe.Pointer(&val)
println(pointer)
u := (*interface{})(pointer)
p := (*u).(*Person)
println(p.Name)
}

After Type a type, can not be mixed any more

config.Config has a method func String(string) string
and I want to mix those methods to my Type Config
1. it is ok when
// type Config struct
type Config struct {
// a struct has many methods
config.Config
Path string
}
// new and call string method
var a Config = &Config{}
a.String("test")
it not ok when
// type Config struct
type (
Configure config.Config
Config struct {
Configure
Path string
}
)
// new and call string method
var a Config = &Config{}
// error, can not call `String()`
a.String("test")
It's well put by https://go101.org/article/type-system-overview.html:
a new defined type and its respective source type in type definitions are two distinct types.
This works:
package main
import(
"fmt"
)
type MyType struct {
Id int
}
func (mt *MyType)Method() {
fmt.Printf("Method called %d\n", mt.Id)
}
type MyOtherType MyType
func main(){
mt := &MyType{Id:3}
mt.Method()
//mt2 := &MyOtherType{Id:5}
//mt2.Method()
}
But if you uncomment mt2.Method(), you get an error:
mt2.Method undefined (type *MyOtherType has no field or method Method)
Composition works differently. A struct does get the methods of the structs of which it's composed:
package main
import (
"fmt"
)
type MyType struct {
Id int
}
func (mt *MyType) Method() {
fmt.Printf("Method called %d\n", mt.Id)
}
type MyOtherType struct {
MyType
}
func main() {
mt := &MyType{Id: 3}
mt.Method()
mt2 := &MyOtherType{MyType{Id: 5}}
mt2.Method()
}
That's the magic of type composition.
$ go run t.go
Method called 3
Method called 5

golang initialize member with struct itself for sync.Mutex and sync.Cond

Here is go code:
type someThing struct {
sync.Mutex
cv *sync.Cond
num int
}
func NewSomething() *someThing {
// how do you do this ?
return &someThing{cv:sync.NewCond(sync.Mutex)}
}
This code fails to compile:
sync.Mutex (type) is not an expression
So basically the question is how to refer to the struct itself (because it has an embedded member sync.Mutex) while initializing it ? (c++ has this, for example).
You can create a new instance first, and then refer to the embedded field:
type SomeThing struct {
sync.Mutex
cv *sync.Cond
num int
}
func NewSomething() *SomeThing {
st := &SomeThing{}
st.cv = sync.NewCond(&st.Mutex)
return st
}
GoPlay here: https://play.golang.org/p/BlnHMi1EKT

How do I put a vector inside of a struct in Go?

I'm trying to put a vector variable inside a struct in Google's Go programming language. This is what I have so far:
Want:
type Point struct { x, y int }
type myStruct struct {
myVectorInsideStruct vector;
}
func main(){
myMyStruct := myStruct{vector.New(0)};
myPoint := Point{2,3};
myMyStruct.myVectorInsideStruct.Push(myPoint);
}
Have:
type Point struct { x, y int }
func main(){
myVector := vector.New(0);
myPoint := Point{2,3};
myVector.Push(myPoint);
}
I can get the vector to work in my main function just fine, but I want to encapsulate it inside a struct for easier use.
I'm not sure whether this is what you want, so leave a comment if it doesn't work:
package main
import "container/vector";
type Point struct { x, y int };
type mystruct struct {
myVectorInsideStruct * vector.Vector;
}
func main() {
var myMyStruct mystruct;
myMyStruct.myVectorInsideStruct = new(vector.Vector);
myPoint := Point{2,3};
myMyStruct.myVectorInsideStruct.Push(myPoint);
}
Not sure this is what you want, but:
package main
import (
"fmt";
"container/vector";
)
type myStruct (
struct {
myVectorInsideStruct vector.IntVector;
}
)
func main() {
v := new(myStruct);
v.myVectorInsideStruct.Init(0);
for i := 1 ; i < 10 ; i++ {
v.myVectorInsideStruct.Push(i);
}
fmt.Printf("v.myVectorInsideStruct: %v\n", v.myVectorInsideStruct.Data());
}

Resources