# Embedding Julia without RTLD\_GLOBAL in dlopen?

**URL:** https://discourse.julialang.org/t/embedding-julia-without-rtld-global-in-dlopen/37655
**Category:** General Usage
**Tags:** embedding
**Created:** [April 15, 2020, 5:00pm UTC](https://discourse.julialang.org/t/embedding-julia-without-rtld-global-in-dlopen/37655 "2020-04-15T17:00:51Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![OliverEvans96](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oliverevans96/32/4177_2.png) [@OliverEvans96](https://discourse.julialang.org/u/OliverEvans96)
#### Post date: [April 15, 2020, 5:00pm UTC](https://discourse.julialang.org/t/embedding-julia-without-rtld-global-in-dlopen/37655/1 "2020-04-15T17:00:52Z")

</div>

Hi all,

I’ll briefly explain my specific problem, then describe the general question with a minimal working example.

# The specific problem

I’m interested in using Julia to create an [LV2](https://lv2plug.in) plugin, which is basically an effect for audio processing (e.g. reverb, distortion, echo). The general setup is that there’s a “host” program which runs and coordinates multiple “plugins”, which each represent an individual transformation of the audio stream.

Both hosts and plugins are generally written in C. The plugin is compiled into a shared object library (`.so`), and the host calls specific functions from the plugin via `dlopen` and `dlsym` in accordance with the LV2 API. There’s a standard library for writing hosts called [Livl](http://drobilla.net/docs/lilv/).

So I want to write a C plugin with embedded Julia doing the heavy lifting. The issue is that hosts call `dlopen` via Livl [here](https://github.com/lv2/lilv/blob/master/src/lib.c#L50) with only the `RTLD_NOW` flag, not the `RTLD_GLOBAL` flag, whereas the [Julia doc page on embedding](https://docs.julialang.org/en/v1/manual/embedding/#High-Level-Embedding-1) says very clearly

> Currently, dynamically linking with the `libjulia` shared library requires passing the `RTLD_GLOBAL` option.

Is it possible to write a plugin with embedded julia without modifying the host code?

# Minimal working example

I’ve created the following MWE, which is also available [on github](https://github.com/OliverEvans96/julia-embed-example), to represent the situation. In this example, we have a host calling one function from a plugin library which contains embedded Julia. It suceeds when the host uses `RTLD_NOW`, but fails otherwise.

plugin.c

```julia-auto
#include <stdio.h>
#include <julia.h>

float plugin_func(float x)
{
  jl_function_t *julia_sqrt;
  jl_value_t *julia_input, *julia_output;
  float result;

  jl_init();

  printf("Plugin - Getting julia function\n");
  julia_sqrt = jl_get_function(jl_main_module, "sqrt");

  printf("Plugin - Boxing input\n");
  julia_input = jl_box_float32(x);

  printf("Plugin - Calling julia function.\n");
  julia_output = jl_call1(julia_sqrt, julia_input);

  printf("Plugin - Unboxing output\n");
  result = jl_unbox_float32(julia_output);

  printf("Plugin - Returning result\n");
  return result;
}

```

host.c

```julia-auto
#include <stdio.h>
#include <dlfcn.h>

int main() {
  void *plugin_lib;
  float(*plugin_func)(float x);
  float plugin_result;

  printf("Host - dlopen\n");
  plugin_lib = dlopen("./plugin.so", RTLD_NOW);

  printf("Host - dlsym\n");
  plugin_func = dlsym(plugin_lib, "plugin_func");

  printf("Host - call plugin_func\n");
  plugin_result = plugin_func(9.0f);
  printf("Host - Plugin returned %.2f\n", plugin_result);

  printf("Host - dlclose\n");
  dlclose(plugin_lib);

  printf("Host - finished\n");
  return 0;
}

```

Makefile

```julia-auto
JFLAGS=$(shell $(shell dirname $(shell which julia))/../share/julia/julia-config.jl --cflags --ldflags --ldlibs)
CC=gcc

host: host.c plugin.so
	$(CC) -std=c99 -Wall -ldl $< -o $@ 

%.so: %.c
	$(CC) -shared -o $@ $(JFLAGS) -fPIC $<

.PHONY: clean

clean:
	rm -f *.so host

```

This example works fine when the host uses `RTLD_GLOBAL` in `dlopen`:

```julia-auto
$ make
gcc -shared -o plugin.so -std=gnu99 -I'/home/oliver/local/src/julia-1.4.0/include/julia' -fPIC -L'/home/oliver/local/src/julia-1.4.0/lib' -Wl,--export-dynamic -Wl,-rpath,'/home/oliver/local/src/julia-1.4.0/lib' -Wl,-rpath,'/home/oliver/local/src/julia-1.4.0/lib/julia' -ljulia -fPIC plugin.c
gcc -std=c99 -Wall -ldl host.c -o host 

$ ./host
Host - dlopen
Host - dlsym
Host - call plugin_func
Plugin - Getting julia function
Plugin - Boxing input
Plugin - Calling julia function.
Plugin - Unboxing output
Plugin - Returning result
Host - Plugin returned 3.00
Host - dlclose
Host - finished

```

But without `RTLD_GLOBAL`, it fails because it can’t access the necessary symbols from libjulia.

```julia-auto
$ sed -i 's/RTLD_NOW | RTLD_GLOBAL/RTLD_NOW/' host.c

$ make
gcc -std=c99 -Wall -ldl host.c -o host 

$ ./host
Host - dlopen
Host - dlsym
Host - call plugin_func
fatal: error thrown and no exception handler available.
ErrorException("could not load symbol "jl_n_threads":
./host: undefined symbol: jl_n_threads")
jl_errorf at /buildworker/worker/package_linux64/build/src/rtutils.c:77
jl_dlsym at /buildworker/worker/package_linux64/build/src/dlload.c:269
jl_load_and_lookup at /buildworker/worker/package_linux64/build/src/runtime_ccall.cpp:63
nthreads at ./threadingconstructs.jl:19 [inlined]
__preinit_threads__ at ./task.jl:518
jfptr ___preinit_threads___ 1959.clone_1 at /home/oliver/local/src/julia-1.4.0/lib/julia/sys.so (unknown line)
_jl_invoke at /buildworker/worker/package_linux64/build/src/gf.c:2144 [inlined]
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2322
jl_apply at /buildworker/worker/package_linux64/build/src/julia.h:1692 [inlined]
_julia_init at /buildworker/worker/package_linux64/build/src/init.c:765
jl_init_with_image__threading at /buildworker/worker/package_linux64/build/src/jlapi.c:74
jl_init__threading at /buildworker/worker/package_linux64/build/src/jlapi.c:102
plugin_func at ./plugin.so (unknown line)
main at ./host (unknown line)
__libc_start_main at /usr/lib/libc.so.6 (unknown line)
_start at ./host (unknown line)

atexit hook threw an error: ErrorException("could not load symbol "jl_array_del_beg":
./host: undefined symbol: jl_array_del_beg")

```

# The general question

I’m not very familiar with compiler/linker details, so forgive my ignorance. But my question becomes:

Is there any way around the `RTLD_GLOBAL` requirement? Is it somehow possible to statically compile `libjulia` into the shared library? Or if not, is it possible to compile a static library/executable which can be `dlopen`’d and `dlsym`’d in the same way a shared library would?

If this is just a current Julia limitation and there’s absolutely no way around it, I’d at least be interested to learn more about the issue and what causes the current dependence on `RTLD_GLOBAL`.

Thanks!  
Oliver

---

<div class="post-metadata">

### Author: ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)
#### Post date: [April 15, 2020, 5:18pm UTC](https://discourse.julialang.org/t/embedding-julia-without-rtld-global-in-dlopen/37655/2 "2020-04-15T17:18:32Z")

</div>

It looks like you can create a shim library that `dlopen`s your actual plugin library with `RTLD_GLOBAL`: [Different behaviours in Linux and MacOs with Julia embedded in C++ - #13 by vitreo12](https://discourse.julialang.org/t/different-behaviours-in-linux-and-macos-with-julia-embedded-in-c/18101/13)

---

<div class="post-metadata">

### Author: ![Orbots](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/orbots/32/3392_2.png) [@Orbots](https://discourse.julialang.org/u/Orbots)
#### Post date: [April 15, 2020, 5:26pm UTC](https://discourse.julialang.org/t/embedding-julia-without-rtld-global-in-dlopen/37655/3 "2020-04-15T17:26:05Z")

</div>

It’s ok to dlopen a lib twice. You can dlopen either your plugin or libjulia.so with RTLD\_GLOBAL from your plugin. This will lift it into the so namespace that julia wants. I used to have a shim library, but now I just do this.

---

<div class="post-metadata">

### Author: ![OliverEvans96](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oliverevans96/32/4177_2.png) [@OliverEvans96](https://discourse.julialang.org/u/OliverEvans96)
#### Post date: [April 15, 2020, 5:47pm UTC](https://discourse.julialang.org/t/embedding-julia-without-rtld-global-in-dlopen/37655/4 "2020-04-15T17:47:41Z")

</div>

@tkf and @Orbots - thanks for the quick and excellent answers! I didn’t expect it to be nearly so easy, but simply adding `dlopen("libjulia.so", RTLD_NOW | RTLD_GLOBAL);` before `jl_init();` in `plugin.c` does the trick!
