diff --git a/generator/gen_bindings.go b/generator/gen_bindings.go index ceb72bd..1749b98 100644 --- a/generator/gen_bindings.go +++ b/generator/gen_bindings.go @@ -315,7 +315,8 @@ The caller is responsible for freeing the this memory via C.free.`, name, cgoSpe } return mem }`, name, sizeofConst) - fmt.Fprintln(buf, "\n") + fmt.Fprintln(buf) + fmt.Fprintln(buf) fmt.Fprintf(buf, `const %s = unsafe.Sizeof([1]%s{})`, sizeofConst, cgoSpec) helper.Source = buf.String() @@ -787,7 +788,7 @@ func (gen *Generator) proxyArgToGo(memTip tl.Tip, varName, ptrName string, } func (gen *Generator) proxyValueToGo(memTip tl.Tip, varName, ptrName string, - goSpec tl.GoTypeSpec, cgoSpec tl.CGoSpec) (proxy string, nillable bool) { + goSpec tl.GoTypeSpec, cgoSpec tl.CGoSpec, lenField string) (proxy string, nillable bool) { nillable = true if goSpec.IsGoString() { @@ -829,7 +830,15 @@ func (gen *Generator) proxyValueToGo(memTip tl.Tip, varName, ptrName string, fmt.Fprintf(buf, "hx%2x := (*sliceHeader)(unsafe.Pointer(&%s))\n", postfix, varName) fmt.Fprintf(buf, "hx%2x.Data = unsafe.Pointer(%s)\n", postfix, ptrName) fmt.Fprintf(buf, "hx%2x.Cap = %s\n", postfix, gen.maxMem) - fmt.Fprintf(buf, "// hx%2x.Len = ?\n", postfix) + + // check if we have a configuration for a custom length property + idx := strings.LastIndex(ptrName, ".") + if lenField != "" && idx > 0 { + // replace the `x.refxxxxx.some_field` suffix with the lenField name + fmt.Fprintf(buf, "hx%2x.Len = int(%s)\n", postfix, ptrName[0:idx+1]+lenField) + } else { + fmt.Fprintf(buf, "// hx%2x.Len = ? %s %s\n", postfix, varName, ptrName) + } proxy = buf.String() return case isPlain: // ex: byte, [4]byte diff --git a/generator/gen_struct_helpers.go b/generator/gen_struct_helpers.go index 410b414..85dfa91 100644 --- a/generator/gen_struct_helpers.go +++ b/generator/gen_struct_helpers.go @@ -208,15 +208,16 @@ func (gen *Generator) getRawStructHelpers(goStructName []byte, cStructName strin goSpec.Pointers += 1 cgoSpec.Pointers += 1 } - fmt.Fprintf(buf,"func (s *%s) Get%s() %s {\n", goStructName, goName, goSpec) - toProxy, _ := gen.proxyValueToGo(memTip, "ret", "&s." + m.Name, goSpec, cgoSpec) - fmt.Fprintf(buf,"\tvar ret %s\n", goSpec) - fmt.Fprintf(buf,"\t%s\n",toProxy) + fmt.Fprintf(buf, "func (s *%s) Get%s() %s {\n", goStructName, goName, goSpec) + lenField := getLenField(gen, structSpec, m) + toProxy, _ := gen.proxyValueToGo(memTip, "ret", "&s."+m.Name, goSpec, cgoSpec, lenField) + fmt.Fprintf(buf, "\tvar ret %s\n", goSpec) + fmt.Fprintf(buf, "\t%s\n", toProxy) fmt.Fprintf(buf, "\treturn ret\n") fmt.Fprintf(buf, "}\n") helpers = append(helpers, &Helper{ - Name: fmt.Sprintf("%s.Get%s", goStructName, goName), - Description: fmt.Sprintf("Get%s returns a reference to C object within a struct",goName), + Name: fmt.Sprintf("%s.Get%s", goStructName, goName), + Description: fmt.Sprintf("Get%s returns a reference to C object within a struct", goName), Source: buf.String(), }) } @@ -345,8 +346,17 @@ func (gen *Generator) getDerefSource(goStructName []byte, cStructName string, sp goName := "x." + string(gen.tr.TransformName(tl.TargetType, m.Name, public)) cgoName := fmt.Sprintf("x.ref%2x.%s", crc, m.Name) cgoSpec := gen.tr.CGoSpec(m.Spec, false) - toProxy, _ := gen.proxyValueToGo(memTip, goName, cgoName, goSpec, cgoSpec) + lenField := getLenField(gen, structSpec, m) + toProxy, _ := gen.proxyValueToGo(memTip, goName, cgoName, goSpec, cgoSpec, lenField) fmt.Fprintln(buf, toProxy) } return buf.Bytes() } + +func getLenField(gen *Generator, structSpec *tl.CStructSpec, m *tl.CDecl) string { + lenField := "" + if gen.tr.LenFields() != nil { + lenField = gen.tr.LenFields()[structSpec.Typedef+"."+m.Name] + } + return lenField +} diff --git a/translator/translator.go b/translator/translator.go index c13bf14..a5df3e3 100644 --- a/translator/translator.go +++ b/translator/translator.go @@ -24,9 +24,10 @@ type Translator struct { builtinTypemap2 CTypeMap ignoredFiles map[string]struct{} - valueMap map[string]Value - exprMap map[string]string - tagMap map[string]*CDecl + valueMap map[string]Value + exprMap map[string]string + tagMap map[string]*CDecl + lenFields map[string]string defines []*CDecl typedefs []*CDecl @@ -78,14 +79,15 @@ func (t TipSpecRx) Self() Tip { } type Config struct { - Rules Rules `yaml:"Rules"` - ConstRules ConstRules `yaml:"ConstRules"` - PtrTips PtrTips `yaml:"PtrTips"` - TypeTips TypeTips `yaml:"TypeTips"` - MemTips MemTips `yaml:"MemTips"` - Typemap CTypeMap `yaml:"Typemap"` - ConstCharIsString *bool `yaml:"ConstCharIsString"` - ConstUCharIsString *bool `yaml:"ConstUCharIsString"` + Rules Rules `yaml:"Rules"` + ConstRules ConstRules `yaml:"ConstRules"` + PtrTips PtrTips `yaml:"PtrTips"` + TypeTips TypeTips `yaml:"TypeTips"` + MemTips MemTips `yaml:"MemTips"` + Typemap CTypeMap `yaml:"Typemap"` + ConstCharIsString *bool `yaml:"ConstCharIsString"` + ConstUCharIsString *bool `yaml:"ConstUCharIsString"` + LenFields map[string]string `yaml:"LenFields"` IgnoredFiles []string `yaml:"-"` LongIs64Bit bool `yaml:"-"` @@ -122,6 +124,7 @@ func New(cfg *Config) (*Translator, error) { valueMap: make(map[string]Value), exprMap: make(map[string]string), tagMap: make(map[string]*CDecl), + lenFields: cfg.LenFields, typedefsSet: make(map[string]struct{}), typedefKinds: make(map[string]CTypeKind), ignoredFiles: make(map[string]struct{}), @@ -1016,6 +1019,10 @@ func (t *Translator) TagMap() map[string]*CDecl { return t.tagMap } +func (t *Translator) LenFields() map[string]string { + return t.lenFields +} + func (t *Translator) ExpressionMap() map[string]string { return t.exprMap }