mirror of
https://github.com/vlang/v.git
synced 2025-09-13 14:32:26 +03:00
parent
be4f7176f4
commit
fd269cad87
4 changed files with 43 additions and 9 deletions
|
@ -10,7 +10,9 @@ module library
|
||||||
// `library__add_1`, if not for the export: tag).
|
// `library__add_1`, if not for the export: tag).
|
||||||
@[export: 'add_1']
|
@[export: 'add_1']
|
||||||
pub fn add_1(x int, y int) int {
|
pub fn add_1(x int, y int) int {
|
||||||
return my_private_function(x + y)
|
num := my_private_function(x + y)
|
||||||
|
println('hello from ${@FN} , num = ${num}')
|
||||||
|
return num
|
||||||
}
|
}
|
||||||
|
|
||||||
// this function is not exported and will not be visible to external programs.
|
// this function is not exported and will not be visible to external programs.
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
module main
|
module main
|
||||||
|
|
||||||
// vtest flaky: true
|
|
||||||
// vtest retry: 3
|
|
||||||
import os
|
import os
|
||||||
import dl
|
import dl
|
||||||
|
|
||||||
|
@ -31,6 +29,7 @@ fn test_can_compile_main_program() {
|
||||||
assert os.is_file(library_file_path)
|
assert os.is_file(library_file_path)
|
||||||
result := v_compile('run use_shared_library.v')
|
result := v_compile('run use_shared_library.v')
|
||||||
// dump(result)
|
// dump(result)
|
||||||
|
assert result.output.contains('hello from add_1 , num = 4')
|
||||||
assert result.output.contains('res: 4')
|
assert result.output.contains('res: 4')
|
||||||
os.rm(library_file_path) or {}
|
os.rm(library_file_path) or {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,14 +13,32 @@ fn C.GetProcAddress(handle voidptr, procname &u8) voidptr
|
||||||
|
|
||||||
fn C.FreeLibrary(handle voidptr) bool
|
fn C.FreeLibrary(handle voidptr) bool
|
||||||
|
|
||||||
|
type FN_vinit_caller = fn ()
|
||||||
|
|
||||||
|
type FN_vcleanup_caller = fn ()
|
||||||
|
|
||||||
// open loads a given module into the address space of the calling process.
|
// open loads a given module into the address space of the calling process.
|
||||||
pub fn open(filename string, flags int) voidptr {
|
pub fn open(filename string, flags int) voidptr {
|
||||||
res := C.LoadLibrary(filename.to_wide())
|
res := C.LoadLibrary(filename.to_wide())
|
||||||
|
// Because LoadLibrary has no constructor, this is a workaround
|
||||||
|
if !isnil(res) {
|
||||||
|
vinit_caller := FN_vinit_caller(sym(res, '_vinit_caller'))
|
||||||
|
if !isnil(vinit_caller) {
|
||||||
|
vinit_caller()
|
||||||
|
}
|
||||||
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
// close frees the loaded a given module.
|
// close frees the loaded a given module.
|
||||||
pub fn close(handle voidptr) bool {
|
pub fn close(handle voidptr) bool {
|
||||||
|
// Because FreeLibrary has no destructor, this is a workaround
|
||||||
|
if !isnil(handle) {
|
||||||
|
vcleanup_caller := FN_vcleanup_caller(sym(handle, '_vcleanup_caller'))
|
||||||
|
if !isnil(vcleanup_caller) {
|
||||||
|
vcleanup_caller()
|
||||||
|
}
|
||||||
|
}
|
||||||
return C.FreeLibrary(handle)
|
return C.FreeLibrary(handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5912,8 +5912,9 @@ fn (mut g Gen) write_init_function() {
|
||||||
g.writeln('\tv__trace_calls__on_call(_SLIT("_vinit"));')
|
g.writeln('\tv__trace_calls__on_call(_SLIT("_vinit"));')
|
||||||
}
|
}
|
||||||
|
|
||||||
if g.use_segfault_handler {
|
if g.use_segfault_handler && !g.pref.is_shared {
|
||||||
// 11 is SIGSEGV. It is hardcoded here, to avoid FreeBSD compilation errors for trivial examples.
|
// 11 is SIGSEGV. It is hardcoded here, to avoid FreeBSD compilation errors for trivial examples.
|
||||||
|
// shared object does not need this
|
||||||
g.writeln('#if __STDC_HOSTED__ == 1\n\tsignal(11, v_segmentation_fault_handler);\n#endif')
|
g.writeln('#if __STDC_HOSTED__ == 1\n\tsignal(11, v_segmentation_fault_handler);\n#endif')
|
||||||
}
|
}
|
||||||
if g.pref.is_bare {
|
if g.pref.is_bare {
|
||||||
|
@ -5928,7 +5929,10 @@ fn (mut g Gen) write_init_function() {
|
||||||
// calling module init functions too, just in case they do fail...
|
// calling module init functions too, just in case they do fail...
|
||||||
g.write('\tas_cast_type_indexes = ')
|
g.write('\tas_cast_type_indexes = ')
|
||||||
g.writeln(g.as_cast_name_table())
|
g.writeln(g.as_cast_name_table())
|
||||||
|
if !g.pref.is_shared {
|
||||||
|
// shared object does not need this
|
||||||
g.writeln('\tbuiltin_init();')
|
g.writeln('\tbuiltin_init();')
|
||||||
|
}
|
||||||
|
|
||||||
if g.nr_closures > 0 {
|
if g.nr_closures > 0 {
|
||||||
g.writeln('\t_closure_mtx_init();')
|
g.writeln('\t_closure_mtx_init();')
|
||||||
|
@ -6020,19 +6024,30 @@ fn (mut g Gen) write_init_function() {
|
||||||
println(g.out.after(fn_vcleanup_start_pos))
|
println(g.out.after(fn_vcleanup_start_pos))
|
||||||
}
|
}
|
||||||
|
|
||||||
needs_constructor := g.pref.is_shared && g.pref.os != .windows
|
if g.pref.is_shared {
|
||||||
if needs_constructor {
|
|
||||||
// shared libraries need a way to call _vinit/2. For that purpose,
|
// shared libraries need a way to call _vinit/2. For that purpose,
|
||||||
// provide a constructor/destructor pair, ensuring that all constants
|
// provide a constructor/destructor pair, ensuring that all constants
|
||||||
// are initialized just once, and that they will be freed too.
|
// are initialized just once, and that they will be freed too.
|
||||||
// Note: os.args in this case will be [].
|
// Note: os.args in this case will be [].
|
||||||
|
if g.pref.os == .windows {
|
||||||
|
g.writeln('// workaround for windows, export _vinit_caller, let dl.open() call it')
|
||||||
|
g.writeln('// NOTE: This is hardcoded in vlib/dl/dl_windows.c.v!')
|
||||||
|
g.writeln('VV_EXPORTED_SYMBOL void _vinit_caller();')
|
||||||
|
} else {
|
||||||
g.writeln('__attribute__ ((constructor))')
|
g.writeln('__attribute__ ((constructor))')
|
||||||
|
}
|
||||||
g.writeln('void _vinit_caller() {')
|
g.writeln('void _vinit_caller() {')
|
||||||
g.writeln('\tstatic bool once = false; if (once) {return;} once = true;')
|
g.writeln('\tstatic bool once = false; if (once) {return;} once = true;')
|
||||||
g.writeln('\t_vinit(0,0);')
|
g.writeln('\t_vinit(0,0);')
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
|
|
||||||
|
if g.pref.os == .windows {
|
||||||
|
g.writeln('// workaround for windows, export _vcleanup_caller, let dl.close() call it')
|
||||||
|
g.writeln('// NOTE: This is hardcoded in vlib/dl/dl_windows.c.v!')
|
||||||
|
g.writeln('VV_EXPORTED_SYMBOL void _vcleanup_caller();')
|
||||||
|
} else {
|
||||||
g.writeln('__attribute__ ((destructor))')
|
g.writeln('__attribute__ ((destructor))')
|
||||||
|
}
|
||||||
g.writeln('void _vcleanup_caller() {')
|
g.writeln('void _vcleanup_caller() {')
|
||||||
g.writeln('\tstatic bool once = false; if (once) {return;} once = true;')
|
g.writeln('\tstatic bool once = false; if (once) {return;} once = true;')
|
||||||
g.writeln('\t_vcleanup();')
|
g.writeln('\t_vcleanup();')
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue