1 // Small stub to produce a module-specific entry point
2 // for a Python module. It assumes/requires that it is
3 // linked with PyStubImpl.o to be useful.
4 //
5 // Note that this quite deliberately doesn't include any PyBind11 headers;
6 // it is designed to be compiled without PyBind11 being available at compile time,
7 // to simplify build requirements in downstream environments.
8 
9 #include <Python.h>
10 #include <memory>
11 
12 #ifndef HALIDE_PYSTUB_GENERATOR_NAME
13 #error "HALIDE_PYSTUB_GENERATOR_NAME must be defined"
14 #endif
15 
16 #ifndef HALIDE_PYSTUB_MODULE_NAME
17 #define HALIDE_PYSTUB_MODULE_NAME HALIDE_PYSTUB_GENERATOR_NAME
18 #endif
19 
20 namespace Halide {
21 class GeneratorContext;
22 namespace Internal {
23 class GeneratorBase;
24 }  // namespace Internal
25 }  // namespace Halide
26 
27 using FactoryFunc = std::unique_ptr<Halide::Internal::GeneratorBase> (*)(const Halide::GeneratorContext &context);
28 
29 extern "C" PyObject *_halide_pystub_impl(const char *module_name, FactoryFunc factory);
30 
31 #define HALIDE_STRINGIFY(x) #x
32 #define HALIDE_TOSTRING(x) HALIDE_STRINGIFY(x)
33 
34 #define _HALIDE_CONCAT(first, second) first##second
35 #define HALIDE_CONCAT(first, second) _HALIDE_CONCAT(first, second)
36 
37 #if !defined(HALIDE_EXPORT)
38 #if defined(WIN32) || defined(_WIN32)
39 #define HALIDE_EXPORT __declspec(dllexport)
40 #else
41 #define HALIDE_EXPORT __attribute__((visibility("default")))
42 #endif
43 #endif
44 
45 static_assert(PY_MAJOR_VERSION >= 3, "Python bindings for Halide require Python 3+");
46 
47 #define _HALIDE_PLUGIN_IMPL(name) extern "C" HALIDE_EXPORT PyObject *PyInit_##name()
48 #define HALIDE_PLUGIN_IMPL(name) _HALIDE_PLUGIN_IMPL(name)
49 
50 // clang-format off
51 
52 namespace halide_register_generator {
53 namespace HALIDE_CONCAT(HALIDE_PYSTUB_GENERATOR_NAME, _ns) {
54     extern std::unique_ptr<Halide::Internal::GeneratorBase> factory(const Halide::GeneratorContext &context);
55 }  // namespace HALIDE_CONCAT(HALIDE_PYSTUB_GENERATOR_NAME,_ns)
56 }  // namespace halide_register_generator
57 
58 HALIDE_PLUGIN_IMPL(HALIDE_PYSTUB_MODULE_NAME) {
59     const auto factory = halide_register_generator::HALIDE_CONCAT(HALIDE_PYSTUB_GENERATOR_NAME, _ns)::factory;
60     return _halide_pystub_impl(HALIDE_TOSTRING(HALIDE_PYSTUB_MODULE_NAME), factory);
61 }
62 
63 // clang-format on
64