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).
|
||||
@[export: 'add_1']
|
||||
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.
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
module main
|
||||
|
||||
// vtest flaky: true
|
||||
// vtest retry: 3
|
||||
import os
|
||||
import dl
|
||||
|
||||
|
@ -31,6 +29,7 @@ fn test_can_compile_main_program() {
|
|||
assert os.is_file(library_file_path)
|
||||
result := v_compile('run use_shared_library.v')
|
||||
// dump(result)
|
||||
assert result.output.contains('hello from add_1 , num = 4')
|
||||
assert result.output.contains('res: 4')
|
||||
os.rm(library_file_path) or {}
|
||||
}
|
||||
|
|
|
@ -13,14 +13,32 @@ fn C.GetProcAddress(handle voidptr, procname &u8) voidptr
|
|||
|
||||
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.
|
||||
pub fn open(filename string, flags int) voidptr {
|
||||
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
|
||||
}
|
||||
|
||||
// close frees the loaded a given module.
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
|
@ -5912,8 +5912,9 @@ fn (mut g Gen) write_init_function() {
|
|||
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.
|
||||
// shared object does not need this
|
||||
g.writeln('#if __STDC_HOSTED__ == 1\n\tsignal(11, v_segmentation_fault_handler);\n#endif')
|
||||
}
|
||||
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...
|
||||
g.write('\tas_cast_type_indexes = ')
|
||||
g.writeln(g.as_cast_name_table())
|
||||
g.writeln('\tbuiltin_init();')
|
||||
if !g.pref.is_shared {
|
||||
// shared object does not need this
|
||||
g.writeln('\tbuiltin_init();')
|
||||
}
|
||||
|
||||
if g.nr_closures > 0 {
|
||||
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))
|
||||
}
|
||||
|
||||
needs_constructor := g.pref.is_shared && g.pref.os != .windows
|
||||
if needs_constructor {
|
||||
if g.pref.is_shared {
|
||||
// shared libraries need a way to call _vinit/2. For that purpose,
|
||||
// provide a constructor/destructor pair, ensuring that all constants
|
||||
// are initialized just once, and that they will be freed too.
|
||||
// Note: os.args in this case will be [].
|
||||
g.writeln('__attribute__ ((constructor))')
|
||||
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('void _vinit_caller() {')
|
||||
g.writeln('\tstatic bool once = false; if (once) {return;} once = true;')
|
||||
g.writeln('\t_vinit(0,0);')
|
||||
g.writeln('}')
|
||||
|
||||
g.writeln('__attribute__ ((destructor))')
|
||||
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('void _vcleanup_caller() {')
|
||||
g.writeln('\tstatic bool once = false; if (once) {return;} once = true;')
|
||||
g.writeln('\t_vcleanup();')
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue