Skip to content

Commit 793487f

Browse files
authored
cgen,builder: fix windows 32bit dll function name mangle (fix #23689) (#23690)
1 parent 01096bc commit 793487f

File tree

4 files changed

+24
-2
lines changed

4 files changed

+24
-2
lines changed

vlib/v/builder/msvc_windows.v

+7
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,13 @@ pub fn (mut v Builder) cc_msvc() {
337337
// Libs are passed to cl.exe which passes them to the linker
338338
a << real_libs.join(' ')
339339
a << '/link'
340+
if v.pref.is_shared {
341+
// generate a .def for export function names, avoid function name mangle
342+
// must put after the /link flag!
343+
def_name := v.pref.out_name[0..v.pref.out_name.len - 4]
344+
a << '/DEF:' + os.quoted_path('${def_name}.def')
345+
}
346+
340347
a << '/nologo' // NOTE: /NOLOGO is explicitly not recognised!
341348
a << '/OUT:${os.quoted_path(v.pref.out_name)}'
342349
a << r.library_paths()

vlib/v/gen/c/cgen.v

+14-1
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,8 @@ mut:
263263
has_debugger bool // $dbg has been used in the code
264264
reflection_strings &map[string]int
265265
defer_return_tmp_var string
266-
vweb_filter_fn_name string // vweb__filter or x__vweb__filter, used by $vweb.html() for escaping strings in the templates, depending on which `vweb` import is used
266+
vweb_filter_fn_name string // vweb__filter or x__vweb__filter, used by $vweb.html() for escaping strings in the templates, depending on which `vweb` import is used
267+
export_funcs []string // for .dll export function names
267268
}
268269

269270
@[heap]
@@ -403,6 +404,7 @@ pub fn gen(files []&ast.File, mut table ast.Table, pref_ &pref.Preferences) GenO
403404
global_g.embedded_data.write(g.embedded_data) or { panic(err) }
404405
global_g.shared_types.write(g.shared_types) or { panic(err) }
405406
global_g.shared_functions.write(g.channel_definitions) or { panic(err) }
407+
global_g.export_funcs << g.export_funcs
406408

407409
global_g.force_main_console = global_g.force_main_console || g.force_main_console
408410

@@ -717,6 +719,15 @@ pub fn gen(files []&ast.File, mut table ast.Table, pref_ &pref.Preferences) GenO
717719
helpers.writeln(fn_def)
718720
}
719721
}
722+
723+
if g.pref.is_shared && g.pref.os == .windows && g.export_funcs.len > 0 {
724+
// generate a .def for export function names, avoid function name mangle
725+
def_name := g.pref.out_name[0..g.pref.out_name.len - 4]
726+
dll_name := g.pref.out_name.all_after_last('\\')
727+
file_content := 'LIBRARY ${dll_name}.dll\n\nEXPORTS\n' + g.export_funcs.join('\n')
728+
os.write_file('${def_name}.def', file_content) or { panic(err) }
729+
}
730+
720731
// End of out_0.c
721732

722733
shelpers := helpers.str()
@@ -6366,6 +6377,7 @@ fn (mut g Gen) write_init_function() {
63666377
if g.pref.os != .windows {
63676378
g.writeln('__attribute__ ((constructor))')
63686379
}
6380+
g.export_funcs << '_vinit_caller'
63696381
g.writeln('void _vinit_caller() {')
63706382
g.writeln('\tstatic bool once = false; if (once) {return;} once = true;')
63716383
if g.nr_closures > 0 {
@@ -6377,6 +6389,7 @@ fn (mut g Gen) write_init_function() {
63776389
if g.pref.os != .windows {
63786390
g.writeln('__attribute__ ((destructor))')
63796391
}
6392+
g.export_funcs << '_vcleanup_caller'
63806393
g.writeln('void _vcleanup_caller() {')
63816394
g.writeln('\tstatic bool once = false; if (once) {return;} once = true;')
63826395
g.writeln('\t_vcleanup();')

vlib/v/gen/c/fn.v

+2
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,7 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) {
367367
}
368368
if is_liveshared {
369369
if g.pref.os == .windows {
370+
g.export_funcs << impl_fn_name
370371
g.definitions.write_string('VV_EXPORTED_SYMBOL ${type_name} ${impl_fn_name}(')
371372
g.write('VV_EXPORTED_SYMBOL ${type_name} ${impl_fn_name}(')
372373
} else {
@@ -538,6 +539,7 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) {
538539
if attr.name == 'export' {
539540
weak := if node.attrs.any(it.name == 'weak') { 'VWEAK ' } else { '' }
540541
g.writeln('// export alias: ${attr.arg} -> ${name}')
542+
g.export_funcs << attr.arg
541543
export_alias := '${weak}${type_name} ${fn_attrs}${attr.arg}(${arg_str})'
542544
g.definitions.writeln('VV_EXPORTED_SYMBOL ${export_alias}; // exported fn ${node.name}')
543545
g.writeln('${export_alias} {')

vlib/v/tests/create_dll/create_win_dll_test.v

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ fn test_create_and_dllmain() {
5454
run_test('clang32')
5555
}
5656
$if msvc {
57-
// run_test('msvc32') // something wrong as it passes when it should fail
57+
run_test('msvc32')
5858
}
5959
}
6060
}

0 commit comments

Comments
 (0)