diff --git a/examples/embedding/LocalModule.jl b/examples/embedding/LocalModule.jl new file mode 100644 index 0000000000000..340bd4bc7f666 --- /dev/null +++ b/examples/embedding/LocalModule.jl @@ -0,0 +1,13 @@ +__precompile__() +module LocalModule + +export myapp + +function myapp() + p = addprocs(1) + @everywhere p println("Taking over the world...") + rmprocs(p) + nothing +end + +end diff --git a/examples/embedding/Makefile b/examples/embedding/Makefile index 38e9bc33b2cae..acfd9baf545ed 100644 --- a/examples/embedding/Makefile +++ b/examples/embedding/Makefile @@ -38,7 +38,14 @@ $(BIN)/embedding$(EXE): $(SRCDIR)/embedding.c $(BIN)/embedding-debug$(EXE): $(SRCDIR)/embedding.c $(CC) $^ -o $@ $(CPPFLAGS_ADD) $(CPPFLAGS) $(CFLAGS_ADD) $(CFLAGS) $(LDFLAGS_ADD) $(LDFLAGS) $(DEBUGFLAGS) -check: $(BIN)/embedding$(EXE) +ifneq ($(abspath $(BIN)),$(abspath $(SRCDIR))) +# for demonstration purposes, our demo code is also installed +# in $BIN, although this would likely not be typical +$(BIN)/LocalModule.jl: $(SRCDIR)/LocalModule.jl + cp $< $@ +endif + +check: $(BIN)/embedding$(EXE) $(BIN)/LocalModule.jl $(JULIA) $(SRCDIR)/embedding-test.jl $< @echo SUCCESS diff --git a/examples/embedding/embedding-test.jl b/examples/embedding/embedding-test.jl index fcdbf7fbf2999..11aaca5b5d258 100644 --- a/examples/embedding/embedding-test.jl +++ b/examples/embedding/embedding-test.jl @@ -20,8 +20,9 @@ end @test stderr == "MethodError: no method matching this_function_has_no_methods()\n" @test success(p) lines = wait(stdout_task) - @test length(lines) == 9 + @test length(lines) == 10 @test parse(Float64, lines[1]) ≈ sqrt(2) @test lines[8] == "called bar" @test lines[9] == "calling new bar" + @test lines[10] == "\tFrom worker 2:\tTaking over the world..." end diff --git a/examples/embedding/embedding.c b/examples/embedding/embedding.c index 712e46dd8b6b4..a1fc6c676620b 100644 --- a/examples/embedding/embedding.c +++ b/examples/embedding/embedding.c @@ -149,6 +149,25 @@ int main() bar(); } + { + // Importing a Julia package + + checked_eval_string("let d = dirname(unsafe_string(Base.JLOptions().julia_bin))\n" + // disable the package manager + " ENV[\"JULIA_PKGDIR\"] = joinpath(d, \"disabled\")\n" + // locate files relative to the "embedding" executable + " empty!(LOAD_PATH)\n" + " push!(LOAD_PATH, d)\n" + // this directory needs to be writable for the example, + // although in real code it usually wouldn't necessarily be used that way + " empty!(Base.LOAD_CACHE_PATH)\n" + " push!(Base.LOAD_CACHE_PATH, tempdir())\n" + "end"); + checked_eval_string("import LocalModule"); + checked_eval_string("LocalModule.myapp()"); + } + + int ret = 0; jl_atexit_hook(ret); return ret; diff --git a/src/jlapi.c b/src/jlapi.c index ebd16f11914ba..eadf3eafc7f27 100644 --- a/src/jlapi.c +++ b/src/jlapi.c @@ -26,19 +26,24 @@ JL_DLLEXPORT char * __cdecl dirname(char *); #else #include #endif +#ifndef _OS_WINDOWS_ +#include +#endif -JL_DLLEXPORT int jl_is_initialized(void) { return jl_main_module!=NULL; } +JL_DLLEXPORT int jl_is_initialized(void) +{ + return jl_main_module != NULL; +} -// First argument is the usr/lib directory where libjulia is, or NULL to guess. -// if that doesn't work, try the full path to the "lib" directory that -// contains lib/julia/sys.ji +// First argument is the usr/bin directory where the julia binary is, or NULL to guess. // Second argument is the path of a system image file (*.ji) relative to the -// first argument path, or relative to the default julia home dir. The default -// is something like ../lib/julia/sys.ji +// first argument path, or relative to the default julia home dir. +// The default is something like ../lib/julia/sys.ji JL_DLLEXPORT void jl_init_with_image(const char *julia_home_dir, const char *image_relative_path) { - if (jl_is_initialized()) return; + if (jl_is_initialized()) + return; libsupport_init(); jl_options.julia_home = julia_home_dir; if (image_relative_path != NULL) @@ -51,17 +56,30 @@ JL_DLLEXPORT void jl_init_with_image(const char *julia_home_dir, JL_DLLEXPORT void jl_init(void) { - char *libjldir = NULL; - + char *libbindir = NULL; +#ifdef _OS_WINDOWS_ void *hdl = (void*)jl_load_dynamic_library_e(NULL, JL_RTLD_DEFAULT); - if (hdl) - libjldir = dirname((char*)jl_pathname_for_handle(hdl)); - if (libjldir) - jl_init_with_image(libjldir, jl_get_default_sysimg_path()); - else { + if (hdl) { + char *to_free = (char*)jl_pathname_for_handle(hdl); + if (to_free) { + libbindir = strdup(dirname(to_free)); + free(to_free); + } + } +#else + Dl_info dlinfo; + if (dladdr((void*)jl_init, &dlinfo) != 0 && dlinfo.dli_fname) { + char *to_free = strdup(dlinfo.dli_fname); + (void)asprintf(&libbindir, "%s" PATHSEPSTRING ".." PATHSEPSTRING "%s", dirname(to_free), "bin"); + free(to_free); + } +#endif + if (!libbindir) { printf("jl_init unable to find libjulia!\n"); abort(); } + jl_init_with_image(libbindir, jl_get_default_sysimg_path()); + free(libbindir); } JL_DLLEXPORT jl_value_t *jl_eval_string(const char *str)