All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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/preprocessor/cat.hpp>
36 #include <boost/python/module.hpp>
37 
38 // Helper macros for module files. If you implement your wrappers for classes
39 // as functions named wrapClassName(), then you can create your module like
40 // this:
41 //
42 // TF_WRAP_MODULE(ModuleName) {
43 // TF_WRAP(ClassName1);
44 // TF_WRAP(ClassName2);
45 // TF_WRAP(ClassName3);
46 // }
47 //
48 
49 // Forward declare the function that will be provided that does the wrapping.
50 static void WrapModule();
51 
52 PXR_NAMESPACE_OPEN_SCOPE
53 
54 TF_API
55 void Tf_PyInitWrapModule(void (*wrapModule)(),
56  const char* packageModule,
57  const char* packageName,
58  const char* packageTag,
59  const char* packageTag2);
60 
61 ARCH_EXPORT
62 void BOOST_PP_CAT(init_module_, MFB_PACKAGE_NAME)() {
63 
64  Tf_PyInitWrapModule(
65  WrapModule,
66  TF_PP_STRINGIZE(MFB_PACKAGE_MODULE),
67  TF_PP_STRINGIZE(MFB_ALT_PACKAGE_NAME),
68  "Wrap " TF_PP_STRINGIZE(MFB_ALT_PACKAGE_NAME),
69  TF_PP_STRINGIZE(MFB_PACKAGE_NAME)
70  );
71 }
72 
73 PXR_NAMESPACE_CLOSE_SCOPE
74 
75 #if PY_MAJOR_VERSION == 2
76 // When we generate boost python bindings for a library named Foo,
77 // we generate a python package that has __init__.py and _Foo.so,
78 // and we put all the python bindings in _Foo.so. The __init__.py
79 // file imports _Foo and then publishes _Foo's symbols as its own.
80 // Since the module with the bindings is named _Foo, the init routine
81 // must be named init_Foo. This little block produces that function.
82 //
83 extern "C"
84 ARCH_EXPORT
85 void BOOST_PP_CAT(init_, MFB_PACKAGE_NAME)() {
86  PXR_NAMESPACE_USING_DIRECTIVE
87  boost::python::detail::init_module
88  (TF_PP_STRINGIZE(BOOST_PP_CAT(_,MFB_PACKAGE_NAME)),
89  TF_PP_CAT(&init_module_, MFB_PACKAGE_NAME));
90 }
91 
92 // We also support the case where both the library contents and the
93 // python bindings go into libfoo.so. We still generate a package named foo
94 // but the __init__.py file in the package foo imports libfoo and
95 // publishes it's symbols as its own. Since the module with the
96 // bindings is named libfoo, the init routine must be named initlibfoo.
97 // This little block produces that function.
98 //
99 // So there are two init routines in every library, but only the one
100 // that matches the name of the python module will be called by python
101 // when the module is imported. So the total cost is a 1-line
102 // function that doesn't get called.
103 //
104 extern "C"
105 ARCH_EXPORT
106 void BOOST_PP_CAT(initlib, MFB_PACKAGE_NAME)() {
107  PXR_NAMESPACE_USING_DIRECTIVE
108  boost::python::detail::init_module
109  (TF_PP_STRINGIZE(BOOST_PP_CAT(lib,MFB_PACKAGE_NAME)),
110  TF_PP_CAT(&init_module_, MFB_PACKAGE_NAME));
111 }
112 
113 #else // Python 3:
114 
115 // These functions serve the same purpose as the python 2 implementations
116 // above, but are updated for the overhauled approach to module initialization
117 // in python 3. In python 3 init<name> is replaced by PyInit_<name>, and
118 // initlib<name> becomes PyInit_lib<name>. The init_module function still
119 // exists, but now takes a struct of input values instead of a list of
120 // parameters. Also, these functions now return a PyObject* instead of void.
121 //
122 // See https://docs.python.org/3/c-api/module.html#initializing-c-modules_
123 //
124 extern "C"
125 ARCH_EXPORT
126 PyObject* BOOST_PP_CAT(PyInit__, MFB_PACKAGE_NAME)() {
127 
128  static struct PyModuleDef moduledef = {
129  PyModuleDef_HEAD_INIT,
130  TF_PP_STRINGIZE(BOOST_PP_CAT(_, MFB_PACKAGE_NAME)), // m_name
131  0, // m_doc
132  -1, // m_size
133  NULL, // m_methods
134  0, // m_reload
135  0, // m_traverse
136  0, // m_clear
137  0, // m_free
138  };
139 
140  PXR_NAMESPACE_USING_DIRECTIVE
141  return boost::python::detail::init_module(moduledef,
142  BOOST_PP_CAT(init_module_, MFB_PACKAGE_NAME));
143 }
144 
145 extern "C"
146 ARCH_EXPORT
147 PyObject* BOOST_PP_CAT(PyInit_lib, MFB_PACKAGE_NAME)() {
148 
149  static struct PyModuleDef moduledef = {
150  PyModuleDef_HEAD_INIT,
151  TF_PP_STRINGIZE(BOOST_PP_CAT(lib, MFB_PACKAGE_NAME)), // m_name
152  0, // m_doc
153  -1, // m_size
154  NULL, // m_methods
155  0, // m_reload
156  0, // m_traverse
157  0, // m_clear
158  0, // m_free
159  };
160 
161  PXR_NAMESPACE_USING_DIRECTIVE
162  return boost::python::detail::init_module(moduledef,
163  BOOST_PP_CAT(init_module_, MFB_PACKAGE_NAME));
164 }
165 
166 #endif
167 
168 
169 #define TF_WRAP_MODULE static void WrapModule()
170 
171 // Declares and calls the class wrapper for x
172 #define TF_WRAP(x) ARCH_HIDDEN void wrap ## x (); wrap ## x ()
Define function attributes.