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
25 #include "pxr/pxr.h"
26 #include "pxr/base/tf/pyFunction.h"
27 #include "pxr/base/tf/pyInterpreter.h"
28 #include "pxr/base/tf/pyUtils.h"
29
30 #include <boost/function.hpp>
31
32 #include <boost/python/def.hpp>
33 #include <boost/python/dict.hpp>
34 #include <boost/python/extract.hpp>
35 #include <boost/python/import.hpp>
36
37 #include <functional>
38
39 using namespace boost::python;
40 PXR_NAMESPACE_USING_DIRECTIVE
41
42 static const char VoidFuncSource[] = "def VoidFunc(): pass\n";
43 static const char BoolFuncSource[] = "def BoolFunc(): return True\n";
44 static const char IntFuncSource[] = "def IntFunc(): return 13\n";
45 #if PY_MAJOR_VERSION < 3
46 static const char LongFuncSource[] = "def LongFunc(): return 17L\n";
47 #endif
48 static const char DoubleFuncSource[] = "def DoubleFunc(): return 19.0\n";
49 static const char StringFuncSource[] = "def StringFunc(): return 'a string'\n";
50 static const char ObjectFuncSource[] = "def ObjectFunc(): return testObject\n";
51
52 template <typename T>
53 static void
AssertCallResult(object callable,T const & expected)54 AssertCallResult(object callable, T const &expected)
55 {
56 extract<std::function<T()>> stdFunc(callable);
57 TF_AXIOM(stdFunc.check());
58 TF_AXIOM(stdFunc()() == expected);
59
60 extract<boost::function<T()>> boostFunc(callable);
61 TF_AXIOM(boostFunc.check());
62 TF_AXIOM(boostFunc()() == expected);
63 }
64
65 static void
AssertCallVoid(object callable)66 AssertCallVoid(object callable)
67 {
68 // As there's no result to check, all we care about is that calling the
69 // function does not throw.
70 extract<std::function<void()>> stdFunc(callable);
71 TF_AXIOM(stdFunc.check());
72 stdFunc()();
73
74 extract<boost::function<void()>> boostFunc(callable);
75 TF_AXIOM(boostFunc.check());
76 boostFunc()();
77 }
78
79 static object
DefineFunc(const char * funcName,const char * funcSource,dict testEnv)80 DefineFunc(const char *funcName, const char *funcSource, dict testEnv)
81 {
82 TfPyRunString(funcSource, Py_single_input, testEnv);
83 return testEnv[funcName];
84 }
85
86 int
main(int argc,char ** argv)87 main(int argc, char **argv)
88 {
89 TfPyInitialize();
90
91 TfPyLock lock;
92
93 // Import Tf to make sure that we get the function wrappings defined in
94 // wrapFunction.cpp.
95 object tfModule = import("pxr.Tf");
96 TF_AXIOM(!tfModule.is_none());
97
98 // Store our test functions in this dictionary rather than the main module.
99 dict testEnv;
100
101 testEnv.update(import(TfPyBuiltinModuleName).attr("__dict__"));
102
103 // Expected results of calling functions
104 const bool expectedBool = true;
105 const int expectedInt = 13;
106 #if PY_MAJOR_VERSION < 3
107 const long expectedLong = 17;
108 #endif
109 const double expectedDouble = 19;
110 const std::string expectedString = "a string";
111 object expectedObject = TfPyEvaluate("object()");
112 testEnv["testObject"] = expectedObject;
113
114 // Define and test regular functions
115 object voidFunc = DefineFunc("VoidFunc", VoidFuncSource, testEnv);
116 TF_AXIOM(!voidFunc.is_none());
117 object boolFunc = DefineFunc("BoolFunc", BoolFuncSource, testEnv);
118 TF_AXIOM(!boolFunc.is_none());
119 object intFunc = DefineFunc("IntFunc", IntFuncSource, testEnv);
120 TF_AXIOM(!intFunc.is_none());
121
122 #if PY_MAJOR_VERSION < 3
123 object longFunc = DefineFunc("LongFunc", LongFuncSource, testEnv);
124 TF_AXIOM(!longFunc.is_none());
125 #endif
126
127 object doubleFunc = DefineFunc("DoubleFunc", DoubleFuncSource, testEnv);
128 TF_AXIOM(!doubleFunc.is_none());
129 object stringFunc = DefineFunc("StringFunc", StringFuncSource, testEnv);
130 TF_AXIOM(!stringFunc.is_none());
131 object objectFunc = DefineFunc("ObjectFunc", ObjectFuncSource, testEnv);
132 TF_AXIOM(!objectFunc.is_none());
133
134 AssertCallVoid(voidFunc);
135 AssertCallResult<bool>(boolFunc, expectedBool);
136 AssertCallResult<int>(intFunc, expectedInt);
137 #if PY_MAJOR_VERSION < 3
138 AssertCallResult<long>(longFunc, expectedLong);
139 #endif
140 AssertCallResult<double>(doubleFunc, expectedDouble);
141 AssertCallResult<std::string>(stringFunc, expectedString);
142 AssertCallResult<object>(objectFunc, expectedObject);
143
144 // Define and test lambda functions
145 object voidLambda = TfPyEvaluate("lambda: None");
146 TF_AXIOM(!voidLambda.is_none());
147 object boolLambda = TfPyEvaluate("lambda: True");
148 TF_AXIOM(!boolLambda.is_none());
149 object intLambda = TfPyEvaluate("lambda: 13");
150 TF_AXIOM(!intLambda.is_none());
151 #if PY_MAJOR_VERSION < 3
152 object longLambda = TfPyEvaluate("lambda: 17L");
153 TF_AXIOM(!longLambda.is_none());
154 #endif
155 object doubleLambda = TfPyEvaluate("lambda: 19.0");
156 TF_AXIOM(!doubleLambda.is_none());
157 object stringLambda = TfPyEvaluate("lambda: 'a string'");
158 TF_AXIOM(!stringLambda.is_none());
159 object objectLambda = TfPyEvaluate("lambda: testObject", testEnv);
160 TF_AXIOM(!objectLambda.is_none());
161
162 AssertCallVoid(voidLambda);
163 AssertCallResult<bool>(boolLambda, expectedBool);
164 AssertCallResult<int>(intLambda, expectedInt);
165 #if PY_MAJOR_VERSION < 3
166 AssertCallResult<long>(longLambda, expectedLong);
167 #endif
168 AssertCallResult<double>(doubleLambda, expectedDouble);
169 AssertCallResult<std::string>(stringLambda, expectedString);
170 AssertCallResult<object>(objectLambda, expectedObject);
171 }
172