114299Sbbruce@ucdavis.edu/*
214299Sbbruce@ucdavis.edu    tests/cross_module_gil_utils.cpp -- tools for acquiring GIL from a different module
314299Sbbruce@ucdavis.edu
414299Sbbruce@ucdavis.edu    Copyright (c) 2019 Google LLC
514299Sbbruce@ucdavis.edu
614299Sbbruce@ucdavis.edu    All rights reserved. Use of this source code is governed by a
714299Sbbruce@ucdavis.edu    BSD-style license that can be found in the LICENSE file.
814299Sbbruce@ucdavis.edu*/
914299Sbbruce@ucdavis.edu#include <pybind11/pybind11.h>
1014299Sbbruce@ucdavis.edu#include <cstdint>
1114299Sbbruce@ucdavis.edu
1214299Sbbruce@ucdavis.edu// This file mimics a DSO that makes pybind11 calls but does not define a
1314299Sbbruce@ucdavis.edu// PYBIND11_MODULE. The purpose is to test that such a DSO can create a
1414299Sbbruce@ucdavis.edu// py::gil_scoped_acquire when the running thread is in a GIL-released state.
1514299Sbbruce@ucdavis.edu//
1614299Sbbruce@ucdavis.edu// Note that we define a Python module here for convenience, but in general
1714299Sbbruce@ucdavis.edu// this need not be the case. The typical scenario would be a DSO that implements
1814299Sbbruce@ucdavis.edu// shared logic used internally by multiple pybind11 modules.
1914299Sbbruce@ucdavis.edu
2014299Sbbruce@ucdavis.edunamespace {
2114299Sbbruce@ucdavis.edu
2214299Sbbruce@ucdavis.edunamespace py = pybind11;
2314299Sbbruce@ucdavis.eduvoid gil_acquire() { py::gil_scoped_acquire gil; }
2414299Sbbruce@ucdavis.edu
2514299Sbbruce@ucdavis.educonstexpr char kModuleName[] = "cross_module_gil_utils";
2614299Sbbruce@ucdavis.edu
2714299Sbbruce@ucdavis.edu#if PY_MAJOR_VERSION >= 3
2814299Sbbruce@ucdavis.edustruct PyModuleDef moduledef = {
2914299Sbbruce@ucdavis.edu    PyModuleDef_HEAD_INIT,
3014299Sbbruce@ucdavis.edu    kModuleName,
3114299Sbbruce@ucdavis.edu    NULL,
3214299Sbbruce@ucdavis.edu    0,
3314299Sbbruce@ucdavis.edu    NULL,
3414299Sbbruce@ucdavis.edu    NULL,
3514299Sbbruce@ucdavis.edu    NULL,
3614299Sbbruce@ucdavis.edu    NULL,
3714299Sbbruce@ucdavis.edu    NULL
3814299Sbbruce@ucdavis.edu};
3914299Sbbruce@ucdavis.edu#else
4014299Sbbruce@ucdavis.eduPyMethodDef module_methods[] = {
4114299Sbbruce@ucdavis.edu    {NULL, NULL, 0, NULL}
4214299Sbbruce@ucdavis.edu};
4314299Sbbruce@ucdavis.edu#endif
4414299Sbbruce@ucdavis.edu
4514299Sbbruce@ucdavis.edu}  // namespace
4614299Sbbruce@ucdavis.edu
4714299Sbbruce@ucdavis.eduextern "C" PYBIND11_EXPORT
4814299Sbbruce@ucdavis.edu#if PY_MAJOR_VERSION >= 3
4914299Sbbruce@ucdavis.eduPyObject* PyInit_cross_module_gil_utils()
5014299Sbbruce@ucdavis.edu#else
5114299Sbbruce@ucdavis.eduvoid initcross_module_gil_utils()
5214299Sbbruce@ucdavis.edu#endif
5314299Sbbruce@ucdavis.edu{
5414299Sbbruce@ucdavis.edu
5514299Sbbruce@ucdavis.edu    PyObject* m =
5614299Sbbruce@ucdavis.edu#if PY_MAJOR_VERSION >= 3
5714299Sbbruce@ucdavis.edu        PyModule_Create(&moduledef);
5814299Sbbruce@ucdavis.edu#else
5914299Sbbruce@ucdavis.edu        Py_InitModule(kModuleName, module_methods);
6014299Sbbruce@ucdavis.edu#endif
6114299Sbbruce@ucdavis.edu
6214299Sbbruce@ucdavis.edu    if (m != NULL) {
6314299Sbbruce@ucdavis.edu        static_assert(
6414299Sbbruce@ucdavis.edu            sizeof(&gil_acquire) == sizeof(void*),
6514299Sbbruce@ucdavis.edu            "Function pointer must have the same size as void*");
6614299Sbbruce@ucdavis.edu        PyModule_AddObject(m, "gil_acquire_funcaddr",
6714299Sbbruce@ucdavis.edu                           PyLong_FromVoidPtr(reinterpret_cast<void*>(&gil_acquire)));
6814299Sbbruce@ucdavis.edu    }
6914299Sbbruce@ucdavis.edu
7014299Sbbruce@ucdavis.edu#if PY_MAJOR_VERSION >= 3
7114299Sbbruce@ucdavis.edu    return m;
7214299Sbbruce@ucdavis.edu#endif
7314299Sbbruce@ucdavis.edu}
74