@@ -50,6 +50,7 @@ fn (mut g Gen) fn_decl(node ast.FnDecl) {
5050 g.definitions.write_string ('#define _v_malloc GC_MALLOC\n ' )
5151 return
5252 }
53+
5354 if g.pref.parallel_cc {
5455 if node.is_anon {
5556 g.write ('static ' )
@@ -64,6 +65,16 @@ fn (mut g Gen) fn_decl(node ast.FnDecl) {
6465 defer {
6566 g.is_direct_array_access = prev_is_direct_array_access
6667 }
68+
69+ // handle `@[c_extern] fn C.some_name() int` declarations:
70+ old_inside_c_extern := g.inside_c_extern
71+ defer {
72+ g.inside_c_extern = old_inside_c_extern
73+ }
74+ if node.language == .c && node.attrs.contains ('c_extern' ) {
75+ g.inside_c_extern = true
76+ }
77+
6778 g.gen_attrs (node.attrs)
6879 mut skip := false
6980 pos := g.out.len
@@ -133,7 +144,9 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) {
133144 // as it's only informative, comment it for now
134145 // g.gen_attrs(it.attrs)
135146 if node.language == .c {
136- return
147+ if ! g.inside_c_extern {
148+ return
149+ }
137150 }
138151
139152 old_is_vlines_enabled := g.is_vlines_enabled
@@ -260,7 +273,7 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) {
260273 }
261274 g.last_fn_c_name = impl_fn_name
262275
263- if node.trace_fns.len > 0 {
276+ if ! g.inside_c_extern && node.trace_fns.len > 0 {
264277 for trace_fn, call_fn in node.trace_fns {
265278 if trace_fn in g.trace_fn_definitions {
266279 continue
@@ -345,6 +358,9 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) {
345358 g.write ('${type_name} ${impl_fn_name} (' )
346359 }
347360 }
361+ } else if g.inside_c_extern {
362+ c_extern_fn_header := 'extern ${type_name} ${fn_attrs}${name.all_after_first('C__')} ('
363+ g.definitions.write_string (c_extern_fn_header)
348364 } else {
349365 if ! (node.is_pub || g.pref.is_debug) {
350366 // Private functions need to marked as static so that they are not exportable in the
@@ -380,7 +396,9 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) {
380396 && ! g.pref.is_test) || skip {
381397 // Just a function header. Builtin function bodies are defined in builtin.o
382398 g.definitions.writeln (');' ) // NO BODY')
383- g.writeln (');' )
399+ if ! g.inside_c_extern {
400+ g.writeln (');' )
401+ }
384402 return
385403 }
386404 if node.params.len == 0 {
@@ -690,7 +708,9 @@ fn (mut g Gen) fn_decl_params(params []ast.Param, scope &ast.Scope, is_variadic
690708 mut heap_promoted := []bool {}
691709 if params.len == 0 {
692710 // in C, `()` is untyped, unlike `(void)`
693- g.write ('void' )
711+ if ! g.inside_c_extern {
712+ g.write ('void' )
713+ }
694714 }
695715 // / mut is_implicit_ctx := false
696716 // Veb actions defined by user can have implicit context
@@ -702,7 +722,9 @@ fn (mut g Gen) fn_decl_params(params []ast.Param, scope &ast.Scope, is_variadic
702722 // }
703723 if g.cur_fn.return_type == typ_veb_result {
704724 // is_implicit_ctx = true
705- g.write('/* veb*/ ')
725+ if !g.inside_c_extern {
726+ g.write('/* veb*/ ')
727+ }
706728 }
707729 }
708730 */
@@ -721,10 +743,14 @@ fn (mut g Gen) fn_decl_params(params []ast.Param, scope &ast.Scope, is_variadic
721743 if param_type_sym.kind == .function && ! typ.has_flag (.option) {
722744 info := param_type_sym.info as ast.FnType
723745 func := info.func
724- g.write ('${g.typ(func.return_type)} (*${caname} )(' )
746+ if ! g.inside_c_extern {
747+ g.write ('${g.typ(func.return_type)} (*${caname} )(' )
748+ }
725749 g.definitions.write_string ('${g.typ(func.return_type)} (*${caname} )(' )
726750 g.fn_decl_params (func.params, unsafe { nil }, func.is_variadic, func.is_c_variadic)
727- g.write (')' )
751+ if ! g.inside_c_extern {
752+ g.write (')' )
753+ }
728754 g.definitions.write_string (')' )
729755 fparams << caname
730756 fparamtypes << param_type_name
@@ -748,14 +774,18 @@ fn (mut g Gen) fn_decl_params(params []ast.Param, scope &ast.Scope, is_variadic
748774 ''
749775 }
750776 s := '${const_prefix}${param_type_name} ${var_name_prefix}${caname} '
751- g.write (s)
777+ if ! g.inside_c_extern {
778+ g.write (s)
779+ }
752780 g.definitions.write_string (s)
753781 fparams << caname
754782 fparamtypes << param_type_name
755783 heap_promoted << heap_prom
756784 }
757785 if i < params.len - 1 {
758- g.write (', ' )
786+ if ! g.inside_c_extern {
787+ g.write (', ' )
788+ }
759789 g.definitions.write_string (', ' )
760790 }
761791
@@ -765,7 +795,9 @@ fn (mut g Gen) fn_decl_params(params []ast.Param, scope &ast.Scope, is_variadic
765795 // }
766796 }
767797 if (g.pref.translated && is_variadic) || is_c_variadic {
768- g.write (', ... ' )
798+ if ! g.inside_c_extern {
799+ g.write (', ... ' )
800+ }
769801 g.definitions.write_string (', ... ' )
770802 }
771803 return fparams, fparamtypes, heap_promoted
0 commit comments