diff --git a/docs/installation.md b/docs/installation.md index 5b615b7..89f23e4 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -191,6 +191,30 @@ The complete mapping of names to their Python API counterparts are: | `pyawaitable_abi` | `PyAwaitable_ABI` | | `PyAwaitableType` | `PyAwaitable_Type` | +## Using Precompiled Headers with PyAwaitable + +Using precompiled headers in a large C extension project is supported, just replace `PYAWAITABLE_THIS_FILE_INIT` with `PYAWAITABLE_USE_PCH` **BEFORE** including your precompiled header file in every source file. + +After that inside of the precompiled header file right after including `pyawaitable.h` add this line: + +```c +DECLARE_PYAWAITABLE_ABI; +``` + +In the source file with the module initialization code: + +```c +PYAWAITABLE_INIT_DEF; +``` + +And then finally after the include of `pch.h` inside of `pch.c` (`pch` is placeholder name for the precompiled header): + +```c +DECLARE_PYAWAITABLE_ABI = NULL; +``` + +After that, all logic from the example code in `test.c` still applies. + ## Vendored Copies PyAwaitable ships a vendorable version of each release, containing both a `pyawaitable.c` and `pyawaitable.h` file. For many users, it's much easier to vendor PyAwaitable than use it off PyPI. You can download the zip file containing a vendorable version [from the releases page](https://github.com/ZeroIntensity/pyawaitable/releases). diff --git a/include/pyawaitable/with.h b/include/pyawaitable/with.h index c472d47..096409a 100644 --- a/include/pyawaitable/with.h +++ b/include/pyawaitable/with.h @@ -2,7 +2,7 @@ #define PYAWAITABLE_WITH_H #include // PyObject -#include // awaitcallback, awaitcallback_err +#include // awaitcallback, awaitcallback_err int pyawaitable_async_with_impl( diff --git a/src/pyawaitable/pyawaitable.h b/src/pyawaitable/pyawaitable.h index 5c62088..7afe2b3 100644 --- a/src/pyawaitable/pyawaitable.h +++ b/src/pyawaitable/pyawaitable.h @@ -58,11 +58,25 @@ typedef struct _pyawaitable_abi defer_callback cb); } PyAwaitableABI; +#ifdef PYAWAITABLE_USE_PCH +/* + * Applications using Precompiled Headers must use this + * define to declare the abi pointer before using + * pyawaitable at all in any file. + * For the main file of a C that contains the module + * initialization code it is the user's responsibility + * to set this to null right after using the macro, but + * before they terminate the current line of code. + */ +#define DECLARE_PYAWAITABLE_ABI \ +extern PyAwaitableABI *pyawaitable_abi +#else #ifdef PYAWAITABLE_THIS_FILE_INIT PyAwaitableABI *pyawaitable_abi = NULL; #else extern PyAwaitableABI *pyawaitable_abi; #endif +#endif #define pyawaitable_new pyawaitable_abi->new #define pyawaitable_cancel pyawaitable_abi->cancel @@ -92,6 +106,22 @@ extern PyAwaitableABI *pyawaitable_abi; #define PyAwaitableType pyawaitable_abi->PyAwaitableType +#ifdef PYAWAITABLE_USE_PCH +#define PYAWAITABLE_INIT_DEF \ +static int \ +pyawaitable_init() \ +{ \ + if (pyawaitable_abi != NULL) \ + return 0; \ +\ + PyAwaitableABI *capsule = PyCapsule_Import("_pyawaitable.abi_v1", 0); \ + if (capsule == NULL) \ + return -1; \ +\ + pyawaitable_abi = capsule; \ + return 0; \ +} +#else #ifdef PYAWAITABLE_THIS_FILE_INIT static int pyawaitable_init() @@ -118,6 +148,7 @@ pyawaitable_init() return -1; } +#endif #endif #ifdef PYAWAITABLE_PYAPI