From 35826ee080d9315b79fa303e348dd6cd71f0ad0f Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Mon, 20 Apr 2026 13:49:50 +0300 Subject: [PATCH] cgen: interface fix --- vlib/v/gen/c/cgen.v | 42 ++++++++++++++++++- ...face_method_embed_ptr_receiver.c.must_have | 2 +- .../iface_method_mut_receiver.c.must_have | 4 +- .../c/testdata/iface_method_order.c.must_have | 10 ++--- 4 files changed, 48 insertions(+), 10 deletions(-) diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 311451d3c..18ae5fc0d 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -11621,6 +11621,7 @@ return ${cast_shared_struct_str}; name = g.specialized_method_name_from_receiver(method, st, name) styp := g.cc_type(method.params[0].typ, true) mut method_call := '${styp}_${name}' + mut adapter_receiver_typ := g.styp(method.params[0].typ) _, embed_types := g.table.find_method_from_embeds(st_sym, method.name) or { ast.Fn{}, []ast.Type{} } @@ -11697,10 +11698,39 @@ return ${cast_shared_struct_str}; methods_wrapper.writeln('}') // .speak = Cat_speak_Interface_Animal_method_wrapper method_call = wrapper_method_name + adapter_receiver_typ = '${cctype}*' } if g.pref.build_mode != .build_module && st != ast.voidptr_type && st != ast.nil_type { - methods_struct.writeln('\t\t._method_${c_fn_name(method.name)} = (void*) ${method_call},') + if cctype == cctype2 { + mut adapter_name := '${cctype}_${name}_Interface_${interface_name}_method_adapter' + method_sym := g.table.sym(method.params[0].typ) + if method_sym.is_builtin() { + adapter_name = 'builtin__${adapter_name}' + } + mut adapter_args := []string{cap: method.params.len - 1} + mut adapter_params := ['void* _x'] + for i in 1 .. method.params.len { + arg := method.params[i] + arg_name := if arg.name.len > 0 { c_name(arg.name) } else { 'arg${i}' } + adapter_params << '${g.styp(arg.typ)} ${arg_name}' + adapter_args << arg_name + } + methods_wrapper.writeln('static inline ${g.ret_styp(method.return_type)} ${adapter_name}(${adapter_params.join(', ')}) {') + methods_wrapper.write_string('\t') + if method.return_type != ast.void_type { + methods_wrapper.write_string('return ') + } + methods_wrapper.write_string('${method_call}((${adapter_receiver_typ})_x') + if adapter_args.len > 0 { + methods_wrapper.write_string(', ${adapter_args.join(', ')}') + } + methods_wrapper.writeln(');') + methods_wrapper.writeln('}') + methods_struct.writeln('\t\t._method_${c_fn_name(method.name)} = ${adapter_name},') + } else { + methods_struct.writeln('\t\t._method_${c_fn_name(method.name)} = (void*) ${method_call},') + } } } // For interface methods not found in the type's explicit methods, @@ -11721,7 +11751,15 @@ return ${cast_shared_struct_str}; methods_wrapper.writeln('static inline string ${wrapper_name}(${cctype}* x) {') methods_wrapper.writeln('\treturn ${str_fn_name}(*x);') methods_wrapper.writeln('}') - methods_struct.writeln('\t\t._method_str = (void*) ${wrapper_name},') + if cctype == cctype2 { + adapter_name := '${cctype}_str_Interface_${interface_name}_method_adapter' + methods_wrapper.writeln('static inline string ${adapter_name}(void* _x) {') + methods_wrapper.writeln('\treturn ${wrapper_name}((${cctype}*)_x);') + methods_wrapper.writeln('}') + methods_struct.writeln('\t\t._method_str = ${adapter_name},') + } else { + methods_struct.writeln('\t\t._method_str = (void*) ${wrapper_name},') + } } } } diff --git a/vlib/v/gen/c/testdata/iface_method_embed_ptr_receiver.c.must_have b/vlib/v/gen/c/testdata/iface_method_embed_ptr_receiver.c.must_have index 332e5c461..f6d2ee1f4 100644 --- a/vlib/v/gen/c/testdata/iface_method_embed_ptr_receiver.c.must_have +++ b/vlib/v/gen/c/testdata/iface_method_embed_ptr_receiver.c.must_have @@ -1 +1 @@ -._method_level = (void*) main__Log_level, +._method_level = main__Log_level_Interface_main__Leveler_method_adapter, diff --git a/vlib/v/gen/c/testdata/iface_method_mut_receiver.c.must_have b/vlib/v/gen/c/testdata/iface_method_mut_receiver.c.must_have index bfe82c7fb..a71ec5ec3 100644 --- a/vlib/v/gen/c/testdata/iface_method_mut_receiver.c.must_have +++ b/vlib/v/gen/c/testdata/iface_method_mut_receiver.c.must_have @@ -1,2 +1,2 @@ -._method__v_free = (void*) main__Bar_free, -._method_next = (void*) main__Bar_next, +._method__v_free = main__Bar_free_Interface_main__Foo_method_adapter, +._method_next = main__Bar_next_Interface_main__Foo_method_adapter, diff --git a/vlib/v/gen/c/testdata/iface_method_order.c.must_have b/vlib/v/gen/c/testdata/iface_method_order.c.must_have index a61aeb1fa..b0540a9ad 100644 --- a/vlib/v/gen/c/testdata/iface_method_order.c.must_have +++ b/vlib/v/gen/c/testdata/iface_method_order.c.must_have @@ -4,15 +4,15 @@ void (*_method_b)(void* _); }; struct _main__Foo_interface_methods main__Foo_name_table[3] = { { -._method_a = (void*) main__Bar_a_Interface_main__Foo_method_wrapper, -._method_b = (void*) main__Bar_b_Interface_main__Foo_method_wrapper, +._method_a = main__Bar_a_Interface_main__Foo_method_adapter, +._method_b = main__Bar_b_Interface_main__Foo_method_adapter, }, { ._method_a = (void*) 0, ._method_b = (void*) 0, }, { -._method_a = (void*) main__Baz_a_Interface_main__Foo_method_wrapper, -._method_b = (void*) main__Baz_b_Interface_main__Foo_method_wrapper, +._method_a = main__Baz_a_Interface_main__Foo_method_adapter, +._method_b = main__Baz_b_Interface_main__Foo_method_adapter, }, -}; \ No newline at end of file +}; -- 2.39.5