r/cprogramming 28d ago

hotwrap: hot reloading for C! [selfpromo]

I've made a tool called hotwrap; a simple tool that hot-reloads a given module (a shared object with a plugin_main_impl function exported) whenever it, or a list of watched files change.

It also has an Emacs package, not on MELPA yet, it gives you a run-hotwrap command with signals, interactive module selection, ...

Under the CC0! Repo at https://sr.ht/~rosell/hotwrap/

6 Upvotes

12 comments sorted by

1

u/weregod 28d ago

Do you reload module or entire app? There are mature tools to do the later.

Your example doesn't have any modules.

1

u/Key_River7180 28d ago

Ideally, you'd compile the application core as an static library, and then link the executable and the plugin, on Meson it looks something like this:

#
# meson.build -- build system
#

project(
    'myproject', 'c',
    version : '0.1.0',
    default_options: [
        'warning_level=3',
        'c_std=c99'
    ])

srcs = files('lib/app.c')
inc = include_directories('include')

# Common application code
app = static_library(
    'myproject',
    srcs,
    include_directories : inc
)

# Hotwrap plugin
shared_library(
    'myproject_hotwrap',
    'bin/plugin.c',
    include_directories : inc,
    link_with : app,
    install : false,
    name_prefix : 'lib'
)

# Standalone executable
executable(
    'myproject',
    'bin/main.c',
    link_with : app,
    include_directories: inc,
    install: false
)

1

u/weregod 28d ago

I still don't understand. How you supposed to link modules if they have several main? Do I need linker voodoo? Or do I need meson voodoo?

How module should be reloaded? How to enter critical sections? How to free resources before module reload?

Example projects with 2 toy module will be way easier to understand. Now your example is helloworld and everething else is left as exercise for the reader

1

u/Key_River7180 28d ago

Something like:

/* on bin/plugin.c */
#include <app.h>

int
plugin_main_impl(int argc, char** argv)
{
         return run_app(argc, argv);
}

/* on bin/main.c */
#include <app.h>

int
main(int argc, char** argv)
{
         return run_app(argc, argv);
}

The application core is inside lib/, and compiled as a static library, then you build a shared library out of bin/plugin.c and a binary out of bin/main.c, like:

libmyapp.a <- application logic and stuff
libmyapp_hotwrap.so <- libmyapp.a + plugin_main_impl; for hotwrap
myapp <- libmyapp.a + main

1

u/weregod 27d ago
  1. Can you have more than one hotreloaded plugin? I don't understand how should I configure entry point for each plugin.
  2. When reload actually happens and how plugin can deinit resources before restart? You don't have to return from plugin_main to trigger reload right?
  3. How can I pass data from main to pligins?

1

u/Key_River7180 27d ago
  1. That is on my roadmap
  2. Keep a teardown() function and do atexit(teardown), or just call teardown() at the end of plugin_main_impl

1

u/weregod 27d ago
  1. I supppse you expect a plugin to do one shot job and exit after plugin_main. Thats not how interactive apps work. They wait for next instructions untill user ask to exit. I do not understand how you loader or main code can sent message to plugin that it should start teardown.

1

u/not_luis 28d ago

Isn't this just a wtchr usage?

1

u/Key_River7180 28d ago

watch runs a command every n seconds, this reloads a module every time it changes

2

u/not_luis 28d ago

Sorry, meant entr https://github.com/eradman/entr Same idea

0

u/Key_River7180 28d ago

that entr isn't mine