Files
zoitechat/plugins/python/generate_plugin.py

110 lines
3.4 KiB
Python
Raw Normal View History

2017-09-02 17:52:25 -04:00
#!/usr/bin/env python3
import sys
import cffi
builder = cffi.FFI()
with open(sys.argv[1]) as f:
output = []
eat_until_endif = 0
for line in f:
if line.startswith('#define'):
continue
2026-01-25 16:13:47 -07:00
elif line.endswith('ZOITECHAT_PLUGIN_H\n'):
2017-09-02 17:52:25 -04:00
continue
elif 'time.h' in line:
output.append('typedef int... time_t;')
elif line.startswith('#if'):
eat_until_endif += 1
elif line.startswith('#endif'):
eat_until_endif -= 1
2026-01-05 23:12:38 -07:00
elif eat_until_endif and '_zoitechat_context' not in line:
2017-09-02 17:52:25 -04:00
continue
else:
output.append(line)
builder.cdef(''.join(output))
builder.embedding_api('''
extern "Python" int _on_py_command(char **, char **, void *);
extern "Python" int _on_load_command(char **, char **, void *);
extern "Python" int _on_unload_command(char **, char **, void *);
extern "Python" int _on_reload_command(char **, char **, void *);
extern "Python" int _on_say_command(char **, char **, void *);
extern "Python" int _on_command_hook(char **, char **, void *);
extern "Python" int _on_print_hook(char **, void *);
2026-01-05 23:12:38 -07:00
extern "Python" int _on_print_attrs_hook(char **, zoitechat_event_attrs *, void *);
2017-09-02 17:52:25 -04:00
extern "Python" int _on_server_hook(char **, char **, void *);
2026-01-05 23:12:38 -07:00
extern "Python" int _on_server_attrs_hook(char **, char **, zoitechat_event_attrs *, void *);
2017-09-02 17:52:25 -04:00
extern "Python" int _on_timer_hook(void *);
extern "Python" int _on_plugin_init(char **, char **, char **, char *, char *);
extern "Python" int _on_plugin_deinit(void);
2026-01-05 23:12:38 -07:00
static zoitechat_plugin *ph;
2017-09-02 17:52:25 -04:00
''')
2026-01-05 23:12:38 -07:00
builder.set_source('_zoitechat_embedded', '''
2017-09-02 17:52:25 -04:00
/* Python's header defines these.. */
#undef HAVE_MEMRCHR
#undef HAVE_STRINGS_H
#include "config.h"
2026-01-05 23:12:38 -07:00
#include "zoitechat-plugin.h"
2017-09-02 17:52:25 -04:00
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#endif
2026-01-05 23:12:38 -07:00
static zoitechat_plugin *ph;
2017-09-02 17:52:25 -04:00
CFFI_DLLEXPORT int _on_plugin_init(char **, char **, char **, char *, char *);
CFFI_DLLEXPORT int _on_plugin_deinit(void);
2026-01-05 23:12:38 -07:00
int zoitechat_plugin_init(zoitechat_plugin *plugin_handle,
2017-09-02 17:52:25 -04:00
char **name_out, char **description_out,
char **version_out, char *arg)
{
#ifdef _WIN32
/* CPython cannot be removed from a process once Py_Initialize has run.
If the embedded interpreter fails to start (e.g. _cffi_backend is
missing), the host responds to our 0 return by g_module_close()ing
this plugin, which would also drop the last reference to pythonXY.dll
and unload it mid-flight; the leftover process-global state then
crashes the process later, e.g. when a server connection spawns the
next thread. Pin this module so FreeLibrary can never unload it. */
HMODULE self_handle;
GetModuleHandleExW (GET_MODULE_HANDLE_EX_FLAG_PIN |
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(LPCWSTR)&zoitechat_plugin_init, &self_handle);
#endif
2017-09-02 17:52:25 -04:00
if (ph != NULL)
{
puts ("Python plugin already loaded\\n");
return 0; /* Prevent loading twice */
}
ph = plugin_handle;
2026-01-25 16:13:47 -07:00
return _on_plugin_init(name_out, description_out, version_out, arg, ZOITECHATLIBDIR);
2017-09-02 17:52:25 -04:00
}
2026-01-05 23:12:38 -07:00
int zoitechat_plugin_deinit(void)
2017-09-02 17:52:25 -04:00
{
int ret = _on_plugin_deinit();
ph = NULL;
return ret;
}
''')
with open(sys.argv[2]) as f:
builder.embedding_init_code(f.read())
builder.emit_c_code(sys.argv[3])