This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch main
in repository ego.
View the commit online.
commit bc1c35f31e299c9d854670b1cffe0e58129aa36f
Author: [email protected] <[email protected]>
AuthorDate: Tue Mar 31 09:08:47 2026 -0600
feat(ego-gen): add Eina_Slice property setter support
Generate []byte setters for properties taking Eina_Slice or
Eina_Rw_Slice by value. C wrapper constructs the slice struct
from pointer + length. Unblocks line_delimiter, input_panel_imdata,
and ip_address setters.
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
---
cmd/ego-gen/generator.go | 1 +
cmd/ego-gen/generator_test.go | 58 +++++++++++++++++++++++++++++++++++++
cmd/ego-gen/main.go | 35 +++++++++++++---------
cmd/ego-gen/templates/class.go.tmpl | 19 +++++++++++-
efl/input_text/entity.go | 16 ++++++++++
efl/io/buffered_stream.go | 16 ++++++++++
efl/io/copier.go | 16 ++++++++++
efl/net/ip_address.go | 16 ++++++++++
efl/ui/textbox.go | 16 ++++++++++
9 files changed, 178 insertions(+), 15 deletions(-)
diff --git a/cmd/ego-gen/generator.go b/cmd/ego-gen/generator.go
index 610645b..44b646e 100644
--- a/cmd/ego-gen/generator.go
+++ b/cmd/ego-gen/generator.go
@@ -103,6 +103,7 @@ type PropertyData struct {
HasSet bool
IsEo bool // true when the value type is an Eo class reference
IsStruct bool // true when the value type is a known struct (e.g. Eina_Size2D)
+ IsSlice bool // true when the value type is Eina_Slice or Eina_Rw_Slice ([]byte)
StructGoType string // e.g. "efl.Size2D"
StructCType string // e.g. "Eina_Size2D"
StructGoFields []string // e.g. ["W", "H"]
diff --git a/cmd/ego-gen/generator_test.go b/cmd/ego-gen/generator_test.go
index 9182629..9ba4014 100644
--- a/cmd/ego-gen/generator_test.go
+++ b/cmd/ego-gen/generator_test.go
@@ -1224,3 +1224,61 @@ func TestGenerateClass_CallbackMethod(t *testing.T) {
}
}
}
+
+func TestGenerateClass_SliceSetter(t *testing.T) {
+ g, outDir := newTestGenerator(t)
+
+ si := GetStructInfo("Eina_Slice")
+ data := ClassData{
+ PackageName: "io",
+ GoName: "Copier",
+ EolianName: "Efl.Io.Copier",
+ CClassName: "EFL_IO_COPIER_CLASS",
+ CClassGetFunc: "efl_io_copier_class_get",
+ CPrefix: "efl_io_copier",
+ EOHeaderFile: "efl_io_copier.eo.h",
+ Properties: []PropertyData{
+ {
+ GoGetter: "LineDelimiter",
+ GoSetter: "SetLineDelimiter",
+ CGetName: "efl_io_copier_line_delimiter_get",
+ CSetName: "efl_io_copier_line_delimiter_set",
+ GoType: "[]byte",
+ CType: "Eina_Slice",
+ HasGet: false,
+ HasSet: true,
+ IsStruct: false,
+ IsSlice: true,
+ StructGoType: si.GoType,
+ StructCType: si.CType,
+ StructGoFields: si.GoFields,
+ StructCFields: si.CFields,
+ StructCFieldTypes: si.CFieldTypes,
+ },
+ },
+ }
+
+ if err := g.GenerateClass(data); err != nil {
+ t.Fatalf("GenerateClass: %v", err)
+ }
+
+ outFile := filepath.Join(outDir, "io", "copier.go")
+ content, err := os.ReadFile(outFile)
+ if err != nil {
+ t.Fatalf("output file not found at %s: %v", outFile, err)
+ }
+
+ src := string(content)
+
+ mustContain := []string{
+ "_ego_set_struct_efl_io_copier_line_delimiter_set",
+ "func (o *Copier) SetLineDelimiter(val []byte)",
+ "Eina_Slice",
+ }
+
+ for _, want := range mustContain {
+ if !strings.Contains(src, want) {
+ t.Errorf("output missing expected pattern %q\nfile content:\n%s", want, src)
+ }
+ }
+}
diff --git a/cmd/ego-gen/main.go b/cmd/ego-gen/main.go
index 42d9761..782812d 100644
--- a/cmd/ego-gen/main.go
+++ b/cmd/ego-gen/main.go
@@ -87,10 +87,8 @@ var methodBlocklist = map[string]bool{
// now handled via known struct support.
// efl.Ui.ImageZoomable — image_region setter now handled via known struct support.
// efl.Ui.Win — hint_base/hint_step now handled via known struct support.
- // efl.Net.IpAddress — address setter takes Eina_Slice struct by value
- "efl_net_ip_address_set": true,
- // efl.Io.BufferedStream — line_delimiter setter takes Eina_Slice by value
- "efl_io_buffered_stream_line_delimiter_set": true,
+ // efl.Net.IpAddress — address setter now handled via slice property support.
+ // efl.Io.BufferedStream — line_delimiter setter now handled via slice property support.
// efl.Ui.Calendar — date setters take Efl_Time (struct tm) by value
"efl_ui_calendar_date_min_set": true,
"efl_ui_calendar_date_max_set": true,
@@ -190,8 +188,7 @@ var methodBlocklist = map[string]bool{
// efl.Ui.Widget — focus_state_apply takes struct by value; theme_apply returns Eina_Error
"efl_ui_widget_focus_state_apply": true,
"efl_ui_widget_theme_apply": true,
- // efl.Io.Copier — line_delimiter takes Eina_Slice by value (struct parameter)
- "efl_io_copier_line_delimiter_set": true,
+ // efl.Io.Copier — line_delimiter setter now handled via slice property support.
// efl.Io — methods returning Eina_Error (integer, not pointer) or taking Eina_*_Slice out-params
"efl_io_closer_close": true,
"efl_io_positioner_seek": true,
@@ -201,8 +198,7 @@ var methodBlocklist = map[string]bool{
// efl.Canvas.GestureRecognizer — returns enum (not a pointer) through pointer path
"efl_gesture_recognizer_recognize": true,
// efl.Canvas.Gesture — hotspot setter now handled via known struct support.
- // efl.Input_Text — imdata setter takes Eina_Slice struct by value
- "efl_input_text_input_panel_imdata_set": true,
+ // efl.Input_Text — imdata setter now handled via slice property support.
// efl.Canvas.Scene — pointer_position has extra out-param
"efl_canvas_scene_pointer_position_get": true,
// efl.Canvas.Textgrid — multiple out-params for palette colors
@@ -1067,6 +1063,7 @@ func buildPropertyData(f *Function, cPrefix string) (PropertyData, error) {
var cType, goType string
var isEo bool
var isStruct bool
+ var isSlice bool
if rt := f.ReturnType(FunctionPropGet); rt != nil {
cType = rt.CType()
goType = CTypeToGo(cType)
@@ -1076,8 +1073,10 @@ func buildPropertyData(f *Function, cPrefix string) (PropertyData, error) {
} else if si != nil && si.IsSlice {
// Eina_Slice / Eina_Rw_Slice: the property getter returns a slice
// struct whose fields include "const void *", which cannot be used
- // as a cgo variable type. Disable the getter for such properties.
+ // as a cgo variable type. Disable the getter; mark as slice setter.
hasGet = false
+ isSlice = true
+ goType = si.GoType
}
} else if getVals := f.PropertyValues(FunctionPropGet); len(getVals) == 1 {
// Single getter value parameter — the C getter returns this type
@@ -1090,10 +1089,11 @@ func buildPropertyData(f *Function, cPrefix string) (PropertyData, error) {
cType = ct
goType = CTypeToGo(ct)
} else if si != nil && si.IsSlice {
- // Eina_Slice / Eina_Rw_Slice: disable getter (see above).
+ // Eina_Slice / Eina_Rw_Slice: disable getter; mark as slice setter.
hasGet = false
+ isSlice = true
cType = ct
- goType = CTypeToGo(ct)
+ goType = si.GoType
} else if IsStructType(ct) {
// Unknown struct: cannot be cast through uintptr_t.
// Disable the getter.
@@ -1115,8 +1115,14 @@ func buildPropertyData(f *Function, cPrefix string) (PropertyData, error) {
cType = pt.CType()
goType = CTypeToGo(cType)
isEo = pt.IsClass()
- if si := GetStructInfo(cType); si != nil && !si.IsSlice {
- isStruct = true
+ if si := GetStructInfo(cType); si != nil {
+ if si.IsSlice {
+ // Eina_Slice / Eina_Rw_Slice setter: treat as slice property.
+ isSlice = true
+ goType = si.GoType
+ } else {
+ isStruct = true
+ }
}
}
}
@@ -1139,9 +1145,10 @@ func buildPropertyData(f *Function, cPrefix string) (PropertyData, error) {
HasSet: hasSet,
IsEo: isEo,
IsStruct: isStruct,
+ IsSlice: isSlice,
}
- if isStruct {
+ if isStruct || isSlice {
si := GetStructInfo(cType)
pd.GoType = si.GoType
pd.StructGoType = si.GoType
diff --git a/cmd/ego-gen/templates/class.go.tmpl b/cmd/ego-gen/templates/class.go.tmpl
index f773821..feba194 100644
--- a/cmd/ego-gen/templates/class.go.tmpl
+++ b/cmd/ego-gen/templates/class.go.tmpl
@@ -170,6 +170,15 @@ static void _ego_set_struct_{{$prop.CSetName}}(Eo *obj{{range $i, $f := $prop.St
}
{{- end}}
{{- end}}
+{{- if $prop.IsSlice}}
+{{- if $prop.HasSet}}
+// _ego_set_struct_{{$prop.CSetName}} wraps the setter, constructing the slice
+// struct from mem pointer and len parameters.
+static void _ego_set_struct_{{$prop.CSetName}}(Eo *obj, {{index $prop.StructCFieldTypes 0}} mem, size_t len) {
+ {{$prop.CSetName}}(obj, ({{$prop.StructCType}}){ .len = len, .mem = mem });
+}
+{{- end}}
+{{- end}}
{{- end}}
{{- range $ctor := .Constructors}}
{{- if $ctor.IsStruct}}
@@ -415,7 +424,15 @@ func (o *{{$.GoName}}) {{$prop.GoSetter}}({{range $i, $v := $prop.MultiSetValues
{{- else}}
// {{$prop.GoSetter}} sets the {{$prop.GoGetter}} property of the {{$.GoName}}.
func (o *{{$.GoName}}) {{$prop.GoSetter}}(val {{if $prop.IsEo}}efl.Objecter{{else}}{{$prop.GoType}}{{end}}) {
-{{- if $prop.IsStruct}}
+{{- if $prop.IsSlice}}
+ var cMem unsafe.Pointer
+ var cLen C.size_t
+ if len(val) > 0 {
+ cMem = unsafe.Pointer(&val[0])
+ cLen = C.size_t(len(val))
+ }
+ C._ego_set_struct_{{$prop.CSetName}}((*C.Eo)(o.Eo()), cMem, cLen)
+{{- else if $prop.IsStruct}}
C._ego_set_struct_{{$prop.CSetName}}((*C.Eo)(o.Eo()){{range $i, $gf := $prop.StructGoFields}}, C.{{index $prop.StructCFieldTypes $i}}(val.{{$gf}}){{end}})
{{- else if $prop.IsEo}}
C.{{$prop.CSetName}}((*C.Eo)(o.Eo()), (*C.Eo)(val.Eo()))
diff --git a/efl/input_text/entity.go b/efl/input_text/entity.go
index 1572f56..db17427 100644
--- a/efl/input_text/entity.go
+++ b/efl/input_text/entity.go
@@ -162,6 +162,11 @@ static void _ego_set_efl_input_text_input_panel_return_key_state_set(Eo *obj, vo
(__typeof__(efl_input_text_input_panel_return_key_state_get((const Eo *)0)))(uintptr_t)val;
efl_input_text_input_panel_return_key_state_set(obj, typed);
}
+// _ego_set_struct_efl_input_text_input_panel_imdata_set wraps the setter, constructing the slice
+// struct from mem pointer and len parameters.
+static void _ego_set_struct_efl_input_text_input_panel_imdata_set(Eo *obj, const void * mem, size_t len) {
+ efl_input_text_input_panel_imdata_set(obj, (Eina_Slice){ .len = len, .mem = mem });
+}
*/
import "C"
@@ -299,6 +304,17 @@ func (o *Entity) SetInputPanelReturnKeyState(val unsafe.Pointer) {
C._ego_set_efl_input_text_input_panel_return_key_state_set((*C.Eo)(o.Eo()), val)
}
+// SetInputPanelImdata sets the InputPanelImdata property of the Entity.
+func (o *Entity) SetInputPanelImdata(val []byte) {
+ var cMem unsafe.Pointer
+ var cLen C.size_t
+ if len(val) > 0 {
+ cMem = unsafe.Pointer(&val[0])
+ cLen = C.size_t(len(val))
+ }
+ C._ego_set_struct_efl_input_text_input_panel_imdata_set((*C.Eo)(o.Eo()), cMem, cLen)
+}
+
// InputPanelShow calls the efl_input_text_input_panel_show method on Entity.
func (o *Entity) InputPanelShow() {
C.efl_input_text_input_panel_show((*C.Eo)(o.Eo()))
diff --git a/efl/io/buffered_stream.go b/efl/io/buffered_stream.go
index 7ce32da..3be9074 100644
--- a/efl/io/buffered_stream.go
+++ b/efl/io/buffered_stream.go
@@ -106,6 +106,11 @@ static void _ego_set_efl_io_buffered_stream_inner_io_set(Eo *obj, void *val) {
(__typeof__(efl_io_buffered_stream_inner_io_get((const Eo *)0)))(uintptr_t)val;
efl_io_buffered_stream_inner_io_set(obj, typed);
}
+// _ego_set_struct_efl_io_buffered_stream_line_delimiter_set wraps the setter, constructing the slice
+// struct from mem pointer and len parameters.
+static void _ego_set_struct_efl_io_buffered_stream_line_delimiter_set(Eo *obj, const void * mem, size_t len) {
+ efl_io_buffered_stream_line_delimiter_set(obj, (Eina_Slice){ .len = len, .mem = mem });
+}
// _ego_ev_EFL_IO_BUFFERED_STREAM_EVENT_WRITE_FINISHED returns the event description pointer using the EFL
// macro, avoiding a conflicting extern declaration for the symbol name.
static const Efl_Event_Description *_ego_ev_EFL_IO_BUFFERED_STREAM_EVENT_WRITE_FINISHED(void) {
@@ -244,6 +249,17 @@ func (o *BufferedStream) SetMaxQueueSizeOutput(val uint) {
C.efl_io_buffered_stream_max_queue_size_output_set((*C.Eo)(o.Eo()), C.size_t(val))
}
+// SetLineDelimiter sets the LineDelimiter property of the BufferedStream.
+func (o *BufferedStream) SetLineDelimiter(val []byte) {
+ var cMem unsafe.Pointer
+ var cLen C.size_t
+ if len(val) > 0 {
+ cMem = unsafe.Pointer(&val[0])
+ cLen = C.size_t(len(val))
+ }
+ C._ego_set_struct_efl_io_buffered_stream_line_delimiter_set((*C.Eo)(o.Eo()), cMem, cLen)
+}
+
// TimeoutInactivity returns the TimeoutInactivity property of the BufferedStream.
func (o *BufferedStream) TimeoutInactivity() float64 {
return float64(C.efl_io_buffered_stream_timeout_inactivity_get((*C.Eo)(o.Eo())))
diff --git a/efl/io/copier.go b/efl/io/copier.go
index a33498a..260fc07 100644
--- a/efl/io/copier.go
+++ b/efl/io/copier.go
@@ -113,6 +113,11 @@ static void _ego_set_efl_io_copier_destination_set(Eo *obj, void *val) {
(__typeof__(efl_io_copier_destination_get((const Eo *)0)))(uintptr_t)val;
efl_io_copier_destination_set(obj, typed);
}
+// _ego_set_struct_efl_io_copier_line_delimiter_set wraps the setter, constructing the slice
+// struct from mem pointer and len parameters.
+static void _ego_set_struct_efl_io_copier_line_delimiter_set(Eo *obj, const void * mem, size_t len) {
+ efl_io_copier_line_delimiter_set(obj, (Eina_Slice){ .len = len, .mem = mem });
+}
// _ego_ev_EFL_IO_COPIER_EVENT_DONE returns the event description pointer using the EFL
// macro, avoiding a conflicting extern declaration for the symbol name.
static const Efl_Event_Description *_ego_ev_EFL_IO_COPIER_EVENT_DONE(void) {
@@ -216,6 +221,17 @@ func (o *Copier) SetDestination(val efl.Objecter) {
C.efl_io_copier_destination_set((*C.Eo)(o.Eo()), (*C.Eo)(val.Eo()))
}
+// SetLineDelimiter sets the LineDelimiter property of the Copier.
+func (o *Copier) SetLineDelimiter(val []byte) {
+ var cMem unsafe.Pointer
+ var cLen C.size_t
+ if len(val) > 0 {
+ cMem = unsafe.Pointer(&val[0])
+ cLen = C.size_t(len(val))
+ }
+ C._ego_set_struct_efl_io_copier_line_delimiter_set((*C.Eo)(o.Eo()), cMem, cLen)
+}
+
// BufferLimit returns the BufferLimit property of the Copier.
func (o *Copier) BufferLimit() uint {
return uint(C.efl_io_copier_buffer_limit_get((*C.Eo)(o.Eo())))
diff --git a/efl/net/ip_address.go b/efl/net/ip_address.go
index 8b43935..6326cae 100644
--- a/efl/net/ip_address.go
+++ b/efl/net/ip_address.go
@@ -110,6 +110,11 @@ static void _ego_set_efl_net_ip_address_sockaddr_set(Eo *obj, void *val) {
(__typeof__(efl_net_ip_address_sockaddr_get((const Eo *)0)))(uintptr_t)val;
efl_net_ip_address_sockaddr_set(obj, typed);
}
+// _ego_set_struct_efl_net_ip_address_set wraps the setter, constructing the slice
+// struct from mem pointer and len parameters.
+static void _ego_set_struct_efl_net_ip_address_set(Eo *obj, const void * mem, size_t len) {
+ efl_net_ip_address_set(obj, (Eina_Slice){ .len = len, .mem = mem });
+}
*/
import "C"
@@ -189,6 +194,17 @@ func (o *IpAddress) SetPort(val unsafe.Pointer) {
C._ego_set_efl_net_ip_address_port_set((*C.Eo)(o.Eo()), val)
}
+// SetAddress sets the Address property of the IpAddress.
+func (o *IpAddress) SetAddress(val []byte) {
+ var cMem unsafe.Pointer
+ var cLen C.size_t
+ if len(val) > 0 {
+ cMem = unsafe.Pointer(&val[0])
+ cLen = C.size_t(len(val))
+ }
+ C._ego_set_struct_efl_net_ip_address_set((*C.Eo)(o.Eo()), cMem, cLen)
+}
+
// Sockaddr returns the Sockaddr property of the IpAddress.
func (o *IpAddress) Sockaddr() unsafe.Pointer {
return unsafe.Pointer(C._ego_get_efl_net_ip_address_sockaddr_get((*C.Eo)(o.Eo())))
diff --git a/efl/ui/textbox.go b/efl/ui/textbox.go
index d6d9708..edce364 100644
--- a/efl/ui/textbox.go
+++ b/efl/ui/textbox.go
@@ -427,6 +427,11 @@ static void _ego_get_struct_efl_ui_scrollable_step_size_get(const Eo *obj, int *
static void _ego_set_struct_efl_ui_scrollable_step_size_set(Eo *obj, int x, int y) {
efl_ui_scrollable_step_size_set(obj, (Eina_Position2D){ .x = x, .y = y });
}
+// _ego_set_struct_efl_input_text_input_panel_imdata_set wraps the setter, constructing the slice
+// struct from mem pointer and len parameters.
+static void _ego_set_struct_efl_input_text_input_panel_imdata_set(Eo *obj, const void * mem, size_t len) {
+ efl_input_text_input_panel_imdata_set(obj, (Eina_Slice){ .len = len, .mem = mem });
+}
// _ego_ev_EFL_UI_TEXTBOX_EVENT_SELECTION_PASTE returns the event description pointer using the EFL
// macro, avoiding a conflicting extern declaration for the symbol name.
static const Efl_Event_Description *_ego_ev_EFL_UI_TEXTBOX_EVENT_SELECTION_PASTE(void) {
@@ -999,6 +1004,17 @@ func (o *Textbox) SetInputPanelReturnKeyState(val unsafe.Pointer) {
C._ego_set_efl_input_text_input_panel_return_key_state_set((*C.Eo)(o.Eo()), val)
}
+// SetInputPanelImdata sets the InputPanelImdata property of the Textbox.
+func (o *Textbox) SetInputPanelImdata(val []byte) {
+ var cMem unsafe.Pointer
+ var cLen C.size_t
+ if len(val) > 0 {
+ cMem = unsafe.Pointer(&val[0])
+ cLen = C.size_t(len(val))
+ }
+ C._ego_set_struct_efl_input_text_input_panel_imdata_set((*C.Eo)(o.Eo()), cMem, cLen)
+}
+
// Text returns the Text property of the Textbox.
func (o *Textbox) Text() string {
cResult := C.efl_text_get((*C.Eo)(o.Eo()))
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.