I'm not sure if I missed something in the documentation, but is there any native support in nim to dynamically load nim libraries/types? For example, when building some sort of plugin architecture? I'm exploring nim out of curiosity, and I often implement some sort of plugin system in larger projects I work on.
The only solution I could see would be to export the procedures via exportc, and then use dynlib to dynamically load the compiled shared library, but that only provides access to the shared library procedures. Is there any standard way to share type definitions between nim projects?
I'll try to explain what I mean by example. Say you have an application with a plugin architecture. Users can add functionality by modifying the configuration of the compiled program, and it will load shared libraries at runtime. In order to accomplish this, the program has two source files named program.c and api.h. The former contains the source code to the program while api.h defines the methods, types, etc. that are needed by plugins to interface with the program. An external plugin is compiled by providing the api.h header to a plugin.c file and compiling a shared library. At runtime, that librarie is loaded and the associated functions are called in accordance with the API.
I don't know what this looks like in nim. We can import C share library procedures, but what if the program and the shared object are both nim binaries? How are types, methods, etc. shared between the two when loading the shared object dynamically at runtime?
there's no difference between a compiled c library and a compiled nim library.
so sharing works exactly the same. In nim's case the api.h file would be api.nim and would contain the types and proc definitions the user might need. in this previous example the api.nim might be something like
type
Foo* = object
name*: string
number*: int
FooProc* = proc(): ptr Foo {.nimcall, gcsafe.}
https://github.com/genotrance/feud is a nim app with a runtime plugin system, so it might be worth checking out.
https://nim-lang.org/docs/nimc.html#dll-generation briefly talks about GC with dlls. You can only have one copy of the GC per process, so you build your app and dlls without a runtime library by using the -d:useNimRtl flag, then include nimrtl.dll, which includes the GC and the rest of the runtime. Or at least I think that's how it works.
The feud project above works a bit differently, since it's using the boehm gc, but it's still only loading a single instance of the GC (via boehmgc64.dll rather than nimrtl.dll).
Awesome, those garbage collector details are exactly what I feared/expected :P
Once again, I appreciate the links, and I'm going to dive into the documentation and that project to get a better understanding of how it should work. That's my biggest fear when opening up a language. There's always a million ways to skin the cat, but I'd prefer to use the "right" or "recommended" approach first, haha.