Use struct names in LuaJIT FFI error messages - luajit

When I do something wrong in LuaJIT FFI, I can get an error message like "Cannot convert struct 129 to struct 141". How can I understand which structs are meant? In my code, all C structs have a typedef, which FFI of course knows about, since it can be used in ffi.new; how do I get LuaJIT to use this typedef as the name?

Answer found while looking at other LuaJIT questions: I need to declare structs as typedef struct $name { ... } $name, not typedef struct { ... } $name which I had.

Related

"cgo argument has Go pointer to Go pointer" when pass pointer from Struct to C method

I am using cgo to calling C method which accept struct pointer as below:
package main
/*
typedef struct Client{
struct real_client c;
} Client;
int doSomething(struct real_client *c ) {
....
}
*/
import "C"
import "fmt"
type Client struct {
client C.Client
}
func main() {
cl := Client{}
C.doSomething(&cl.client.c);
// no compile error
}
However, I get an error : cgo argument has Go pointer to Go pointer.
I am using go version go1.16.13.
Is that any way to do make it work ?
Is that any way to do make it work ?
You can set the environment variable GODEBUG to cgocheck=0.
See https://pkg.go.dev/cmd/cgo#hdr-Passing_pointers.
Keep in mind the mechanism exists to prevent C code accessing managed memory not pinned for the duration of the C function call. This can become relevant in the future when changes to Go's garbage collector pertaining memory relocation may be made.

Go / Cgo - How to access a field of a Cstruct?

I develope an application in Go for transcode an audio file from one format to another one:
I use the goav library that use Cgo to bind the FFmpeg C-libs:
https://github.com/giorgisio/goav/
The goav library; package avformat has a typedef that cast the original FFmpeg lib C-Struct AVOutputFormat:
type (
OutputFormat C.struct_AVOutputFormat
)
In my code i have a variable called outputF of the type OutputFormat that is a C.struct_AVOutputFormat.
The C real AVOutputFormat struct has fields:
name, long_name, mime_type, extensions, audio_codec, video_codec, subtitle_codec,..
and many fields more.
See: https://ffmpeg.org/doxygen/2.6/structAVOutputFormat.html
I verified the situation by fmt.Println(outputF) and reached:
{0x7ffff7f23383 0x7ffff7f23907 0x7ffff7f13c33 0x7ffff7f23383 86017 61 0 128 <nil> 0x7ffff7f8cfa0 <nil> 3344 0x7ffff7e3ec10 0x7ffff7e3f410 0x7ffff7e3ecc0 <nil> 0x7ffff7e3dfc0 <nil> <nil> <nil> <nil> <nil> <nil> 0 0x7ffff7e3e070 0x7ffff7e3e020 <nil>}
The audio codec field is on position 5 and contains 86017
I verified the field name by using the package reflect:
val := reflect.Indirect(reflect.ValueOf(outputF))
fmt.Println(val)
fmt.Println("Fieldname: ", val.Type().Field(4).Name)
Output:
Fieldname: audio_codec
I try to access the field audio_codec of the original AVOutputFormat using:
fmt.Println(outputF.audio_codec)
ERROR: outputF.audio_codec undefined (cannot refer to unexported field or method audio_codec)
fmt.Println(outputF._audio_codec)
ERROR: outputF._audio_codec undefined (type *avformat.OutputFormat has no field or method _audio_codec)
As i read in the Cgo documentation:
Within the Go file, C's struct field names that are keywords in Go can be accessed by prefixing them with an underscore: if x points at a C struct with a field named "type", x._type accesses the field. C struct fields that cannot be expressed in Go, such as bit fields or misaligned data, are omitted in the Go struct, replaced by appropriate padding to reach the next field or the end of the struct.
But I have no idea what im doing wrong.
Edit:
Okay for sure no underscore is required as audio_codec is not a keyword in Go. This i understood for now. But still there is the question why im not able to access the CStruct field "audio_codec".
There are some idiosyncrasies to GO/CGO that you're bumping into here:
type OutputFormat C.struct_AVOutputFormat is a go type declaration, not an alias. It might help to think of it as a thin wrapper rather than an alias. Therefore OutputFormat != C.struct_AVOutputFormat and the fields of C.struct_AVOutputFormat are not exported which is why you're getting the ERROR: outputF.audio_codec undefined (cannot refer to unexported field or method audio_codec)
If the field was called Audio_codec it would fit go's definition of an exported identifier and we could access it, but it isn't.
There is a way to get around this, but I'd recommend thinking twice before going ahead with it as it uses unsafe pointers and there are risks that your program may lose portability and/or stability at runtime. This is a good intro to unsafe pointers if you'd like to learn more.
Now if you're really sure you want to do this, the solution is to convert the pointer to OutputFormat into an unsafe pointer then convert it into a pointer to C.struct_AVOutputFormat. Note that this requires you to load the FFMPEG headers to get the definition of C.struct_AVOutputFormat
//#cgo pkg-config: libavformat
//#include <libavformat/avformat.h>
import "C"
import (
"fmt"
"unsafe"
"github.com/giorgisio/goav/avformat"
)
func getOutput() *avformat.OutputFormat {
// calls out to avformat and gets an OutputFormat back
}
func main() {
outputF := getOutput()
coutput := *(*C.struct_AVOutputFormat)(unsafe.Pointer(outputF))
fmt.Println(coutput.audio_codec) // This should now work
}
Caveat: I've not tested that the cgo package config and <libavformat/avformat.h> import are correct but this worked with a simple C library I stood up to try it out with.

Typecasting structs with same underlying types

For basic types we can easily cast the types if their underlying types are same .But the fields inside struct with same memory layout cannot be easily cast from one to another type.
There is a proposal for this problem unfortunately it got rejected .After an hour of googling with no luck I came here seeking the help from experts.
Look at example below
:
package main
import (
"fmt"
)
type Int int
type A struct {
name string
age Int
}
type B struct {
name string
age int
}
func main() {
var a A= A{"Foo",21}
var b B= B{"Bar", 21}
fmt.Println(a,b,(A)(b)) //Error here as expected
}
Eventhough struct A and B has the same underlying type of struct { string,int} why cannot I cast to each other as the underlying type of Int is int.
Whether it is possible to cast recursively unless the underlying type differs?
You can't do it simply because the language spec does not allow it. Regarding structs, you can only convert from one type to the other if Spec: Conversion:
A non-constant value x can be converted to type T in any of these cases:
...
ignoring struct tags (see below), x's type and T have identical underlying types.
If you're absolutely sure the structs' memory layout is identical, you may use an unsafe conversion (using package unsafe) like this:
var a A = A{"Foo", 21}
var b B
b = *(*B)(unsafe.Pointer(&a))
fmt.Println(a, b)
This will output (try it on the Go Playground):
{Foo 21} {Foo 21}
But use this as the last resort. Using unsafe you lose compile time type safety and portability guarantees. E.g. if later you only modify one of the structs, the above code will continue to compile even though it might not be correct anymore, and the compiler will not able to inform you about that.

How does this code work, and where is this syntax documented?

I found a github snippet custom unmarshaling JSON at https://gist.github.com/miguelmota/904f0fdad34eaac09c5d53098f960c5c. It works well, but I hate using code I don't understand.
Specifically, this part uses syntax I'm not familiar with:
type Alias MyStruct
aux := &struct {
SomeCustomType int64 `json:"someCustomType"`
*Alias
}{
Alias: (*Alias)(s),
}
I understand a new type, Alias is being declared, and that it has the same fields as MyStruct. aux is initialized as a pointer to a struct with a redefined field SomeCustomType.
What I've not seen before is the declaration of Alias within the aux struct - (*Alias)(s).
What is this actually doing? Where can I find the documentation on this piece of Go syntax?
The section { Alias: (*Alias)(s) } is not a declaration, it's a struct literal.
A struct literal sets the fields of a struct (in this case, an anonymous struct). Let's break it down:
The Alias: part is setting the embedded field of the struct. Since the struct embeds *Alias, it does not have a field name for it, and the type is used instead.
The (*Alias)(s) part is an explicit type conversion, changing whatever s is to the type *Alias (as long the types are compatible).

Is it possible to find the return type of a boost::function from it's typedef?

Is it possible to find the return type of a boost::function purely from its typedef?
Example:
typedef boost::function<bool (int, float)> CallbackType1;
typedef boost::function<float (int, float)> CallbackType2;
How to find the return type of the above function types?
I'm not sure if using c++0x features will be possible in my target build system, but any solution is welcome.
Many Thanks Guys,
Sak
Boost.Function has a typedef inside it called return_type that should do the trick:
typedef CallbackType1::result_type CallbackType1ReturnType;
No wizardry needed.

Resources