Loading...
Searching...
No Matches
pyModule.h
1//
2// Copyright 2016 Pixar
3//
4// Licensed under the Apache License, Version 2.0 (the "Apache License")
5// with the following modification; you may not use this file except in
6// compliance with the Apache License and the following modification to it:
7// Section 6. Trademarks. is deleted and replaced with:
8//
9// 6. Trademarks. This License does not grant permission to use the trade
10// names, trademarks, service marks, or product names of the Licensor
11// and its affiliates, except as required to comply with Section 4(c) of
12// the License and to reproduce the content of the NOTICE file.
13//
14// You may obtain a copy of the Apache License at
15//
16// http://www.apache.org/licenses/LICENSE-2.0
17//
18// Unless required by applicable law or agreed to in writing, software
19// distributed under the Apache License with the above modification is
20// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21// KIND, either express or implied. See the Apache License for the specific
22// language governing permissions and limitations under the Apache License.
23//
24#ifdef PXR_BASE_TF_PY_MODULE_H
25#error This file should only be included once in any given source (.cpp) file.
26#endif
27#define PXR_BASE_TF_PY_MODULE_H
28
29#include "pxr/pxr.h"
30
32#include "pxr/base/tf/api.h"
33#include "pxr/base/tf/preprocessorUtilsLite.h"
34
35#include <boost/python/module.hpp>
36
37// Helper macros for module files. If you implement your wrappers for classes
38// as functions named wrapClassName(), then you can create your module like
39// this:
40//
41// TF_WRAP_MODULE(ModuleName) {
42// TF_WRAP(ClassName1);
43// TF_WRAP(ClassName2);
44// TF_WRAP(ClassName3);
45// }
46//
47
48// Forward declare the function that will be provided that does the wrapping.
49static void WrapModule();
50
51PXR_NAMESPACE_OPEN_SCOPE
52
53TF_API
54void Tf_PyInitWrapModule(void (*wrapModule)(),
55 const char* packageModule,
56 const char* packageName,
57 const char* packageTag,
58 const char* packageTag2);
59
60ARCH_EXPORT
61void TF_PP_CAT(init_module_, MFB_PACKAGE_NAME)() {
62
63 Tf_PyInitWrapModule(
64 WrapModule,
65 TF_PP_STRINGIZE(MFB_PACKAGE_MODULE),
66 TF_PP_STRINGIZE(MFB_ALT_PACKAGE_NAME),
67 "Wrap " TF_PP_STRINGIZE(MFB_ALT_PACKAGE_NAME),
68 TF_PP_STRINGIZE(MFB_PACKAGE_NAME)
69 );
70}
71
72PXR_NAMESPACE_CLOSE_SCOPE
73
74// When we generate boost python bindings for a library named Foo,
75// we generate a python package that has __init__.py and _Foo.so,
76// and we put all the python bindings in _Foo.so. The __init__.py
77// file imports _Foo and then publishes _Foo's symbols as its own.
78// Since the module with the bindings is named _Foo, the PyInit routine
79// must be named PyInit_Foo. This little block produces that function.
80//
81// See https://docs.python.org/3/c-api/module.html#initializing-c-modules_
82//
83extern "C"
84ARCH_EXPORT
85PyObject* TF_PP_CAT(PyInit__, MFB_PACKAGE_NAME)() {
86
87 static struct PyModuleDef moduledef = {
88 PyModuleDef_HEAD_INIT,
89 TF_PP_STRINGIZE(TF_PP_CAT(_, MFB_PACKAGE_NAME)), // m_name
90 0, // m_doc
91 -1, // m_size
92 NULL, // m_methods
93 0, // m_reload
94 0, // m_traverse
95 0, // m_clear
96 0, // m_free
97 };
98
99 PXR_NAMESPACE_USING_DIRECTIVE
100 return boost::python::detail::init_module(moduledef,
101 TF_PP_CAT(init_module_, MFB_PACKAGE_NAME));
102}
103
104// We also support the case where both the library contents and the
105// python bindings go into libfoo.so. We still generate a package named foo
106// but the __init__.py file in the package foo imports libfoo and
107// publishes it's symbols as its own. Since the module with the
108// bindings is named libfoo, the init routine must be named PyInit_libfoo.
109// This little block produces that function.
110//
111// So there are two init routines in every library, but only the one
112// that matches the name of the python module will be called by python
113// when the module is imported. So the total cost is a 1-line
114// function that doesn't get called.
115//
116extern "C"
117ARCH_EXPORT
118PyObject* TF_PP_CAT(PyInit_lib, MFB_PACKAGE_NAME)() {
119
120 static struct PyModuleDef moduledef = {
121 PyModuleDef_HEAD_INIT,
122 TF_PP_STRINGIZE(TF_PP_CAT(lib, MFB_PACKAGE_NAME)), // m_name
123 0, // m_doc
124 -1, // m_size
125 NULL, // m_methods
126 0, // m_reload
127 0, // m_traverse
128 0, // m_clear
129 0, // m_free
130 };
131
132 PXR_NAMESPACE_USING_DIRECTIVE
133 return boost::python::detail::init_module(moduledef,
134 TF_PP_CAT(init_module_, MFB_PACKAGE_NAME));
135}
136
137
138#define TF_WRAP_MODULE static void WrapModule()
139
140// Declares and calls the class wrapper for x
141#define TF_WRAP(x) ARCH_HIDDEN void wrap ## x (); wrap ## x ()
Define function attributes.