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
27 #include "pxr/base/tf/declarePtrs.h"
28 #include "pxr/base/tf/enum.h"
29 #include "pxr/base/tf/error.h"
30 #include "pxr/base/tf/makePyConstructor.h"
31 #include "pxr/base/tf/notice.h"
32 #include "pxr/base/tf/pyCall.h"
33 #include "pxr/base/tf/pyClassMethod.h"
34 #include "pxr/base/tf/pyEnum.h"
35 #include "pxr/base/tf/pyFunction.h"
36 #include "pxr/base/tf/pyPtrHelpers.h"
37 #include "pxr/base/tf/pyResultConversions.h"
38 #include "pxr/base/tf/refPtr.h"
39 #include "pxr/base/tf/staticData.h"
40 #include "pxr/base/tf/weakPtr.h"
41
42 #include "pxr/base/tf/pyArg.h"
43 #include "pxr/base/tf/pyPolymorphic.h"
44
45 #include <boost/assign/list_of.hpp>
46 #include <boost/python/class.hpp>
47 #include <boost/python/def.hpp>
48 #include <boost/python/list.hpp>
49 #include <boost/python/make_constructor.hpp>
50 #include <boost/python/manage_new_object.hpp>
51 #include <boost/python/pure_virtual.hpp>
52 #include <boost/python/register_ptr_to_python.hpp>
53 #include <boost/python/return_arg.hpp>
54 #include <boost/python/tuple.hpp>
55
56 #include <boost/smart_ptr.hpp>
57
58 #include <functional>
59 #include <string>
60 #include <vector>
61
62 using namespace boost::python;
63 using std::string;
64 using std::vector;
65
66 PXR_NAMESPACE_USING_DIRECTIVE
67
68 PXR_NAMESPACE_OPEN_SCOPE
69
70 // Base
71 typedef TfWeakPtr<class Tf_TestBase> Tf_TestBasePtr;
72 typedef TfWeakPtr<const class Tf_TestBase> Tf_TestBaseConstPtr;
73 typedef TfRefPtr<class Tf_TestBase> Tf_TestBaseRefPtr;
74 class Tf_TestBase : public TfRefBase, public TfWeakBase {
75 public:
~Tf_TestBase()76 virtual ~Tf_TestBase() {}
77 virtual string Virtual() const = 0;
78 virtual void Virtual2() const = 0;
79 virtual void Virtual3(string const &arg) = 0;
80
Virtual4() const81 virtual string Virtual4() const { return "cpp base"; }
82
VirtualCaller() const83 string VirtualCaller() const { return UnwrappedVirtual(); }
84 virtual string UnwrappedVirtual() const = 0;
85 protected:
Tf_TestBase()86 Tf_TestBase() {}
87 };
88
89 // Derived
90 typedef TfWeakPtr<class Tf_TestDerived> Tf_TestDerivedPtr;
91 typedef TfRefPtr<class Tf_TestDerived> Tf_TestDerivedRefPtr;
92 class Tf_TestDerived : public Tf_TestBase {
93 public:
94 // CODE_COVERAGE_OFF_GCOV_BUG woot
~Tf_TestDerived()95 virtual ~Tf_TestDerived() {}
96 // CODE_COVERAGE_ON_GCOV_BUG
Virtual() const97 virtual string Virtual() const { return "cpp derived"; }
Virtual2() const98 virtual void Virtual2() const {}
Virtual3(string const & arg)99 virtual void Virtual3(string const &arg) {
100 printf("cpp derived v3! : %s\n", arg.c_str());
101 }
UnwrappedVirtual() const102 virtual string UnwrappedVirtual() const { return "cpp derived"; }
103
Factory()104 static Tf_TestDerivedRefPtr Factory() {
105 return TfCreateRefPtr(new Tf_TestDerived());
106 }
NullFactory()107 static Tf_TestDerivedRefPtr NullFactory() {
108 return Tf_TestDerivedRefPtr();
109 }
110 protected:
Tf_TestDerived()111 Tf_TestDerived() {}
112 };
113
114
TakesConstBase(Tf_TestBaseConstPtr base)115 static string TakesConstBase(Tf_TestBaseConstPtr base) {
116 return base->Virtual();
117 }
118
ReturnsConstBase(Tf_TestBaseConstPtr base)119 static Tf_TestBaseConstPtr ReturnsConstBase(Tf_TestBaseConstPtr base) {
120 return base;
121 }
122
ReturnsBase(Tf_TestBasePtr base)123 static Tf_TestBasePtr ReturnsBase(Tf_TestBasePtr base) {
124 return base;
125 }
126
ReturnsBaseRefPtr(Tf_TestBasePtr base)127 static Tf_TestBaseRefPtr ReturnsBaseRefPtr(Tf_TestBasePtr base) {
128 return base;
129 }
130
TakesBase(Tf_TestBasePtr base)131 static tuple TakesBase(Tf_TestBasePtr base) {
132 base->Virtual3("hello from TakesConstBase");
133 base->Virtual2();
134 bool isDerived = TfDynamic_cast<Tf_TestDerivedPtr>(base);
135 return boost::python::make_tuple(isDerived, base->Virtual());
136 }
137
TakesDerived(Tf_TestDerivedPtr derived)138 static string TakesDerived(Tf_TestDerivedPtr derived) {
139 derived->Virtual3("A call to virtual 3!");
140 return derived->Virtual();
141 }
142
TakesReference(Tf_TestDerivedRefPtr const & derived)143 static void TakesReference(Tf_TestDerivedRefPtr const &derived) {}
144
TF_REGISTRY_FUNCTION(TfType)145 TF_REGISTRY_FUNCTION(TfType)
146 {
147 TfType::Define< Tf_TestBase >();
148 TfType::Define< Tf_TestDerived, TfType::Bases< Tf_TestBase > >();
149 }
150
151 ////////////////////////////////
152
153 template <typename T = Tf_TestBase>
154 struct polymorphic_Tf_TestBase : public T, public TfPyPolymorphic<T> {
155 typedef polymorphic_Tf_TestBase This;
Virtualpolymorphic_Tf_TestBase156 virtual string Virtual() const {
157 return this->template CallPureVirtual<string>("Virtual")();
158 }
Virtual2polymorphic_Tf_TestBase159 virtual void Virtual2() const {
160 return this->template CallPureVirtual<void>("Virtual2")();
161 }
Virtual3polymorphic_Tf_TestBase162 virtual void Virtual3(string const &arg) {
163 return this->template CallPureVirtual<void>("Virtual3")(arg);
164 }
default_Virtual4polymorphic_Tf_TestBase165 string default_Virtual4() const { return T::Virtual4(); }
Virtual4polymorphic_Tf_TestBase166 virtual string Virtual4() const {
167 return this->CallVirtual("Virtual4", &This::default_Virtual4)();
168 }
UnwrappedVirtualpolymorphic_Tf_TestBase169 virtual string UnwrappedVirtual() const {
170 return this->template CallPureVirtual<string>("UnwrappedVirtual")();
171 }
172
173 };
174
175 static string
callVirtual(Tf_TestBase * base)176 callVirtual(Tf_TestBase * base)
177 {
178 return base->VirtualCaller();
179 }
180
181 template <typename T = Tf_TestDerived>
182 struct polymorphic_Tf_TestDerived : public polymorphic_Tf_TestBase<T> {
183 typedef polymorphic_Tf_TestDerived This;
default_Virtualpolymorphic_Tf_TestDerived184 string default_Virtual() const { return T::Virtual(); }
Virtualpolymorphic_Tf_TestDerived185 virtual string Virtual() const {
186 return this->CallVirtual("Virtual", &This::default_Virtual)();
187 }
default_Virtual2polymorphic_Tf_TestDerived188 void default_Virtual2() const { return T::Virtual2(); }
Virtual2polymorphic_Tf_TestDerived189 virtual void Virtual2() const {
190 return this->CallVirtual("Virtual2", &This::default_Virtual2)();
191 }
default_Virtual3polymorphic_Tf_TestDerived192 void default_Virtual3(string const &arg) { return T::Virtual3(arg); }
Virtual3polymorphic_Tf_TestDerived193 virtual void Virtual3(string const &arg) {
194 return this->CallVirtual("Virtual3", &This::default_Virtual3)(arg);
195 }
196 };
197
198
199 template <typename T>
200 static TfRefPtr<T>
__Ref_init__()201 __Ref_init__() {
202 return TfCreateRefPtr(new T);
203 }
204
205
206 enum TfPyTestErrorCodes {
207 TF_TEST_ERROR_1,
208 TF_TEST_ERROR_2
209 };
210
TF_REGISTRY_FUNCTION(TfEnum)211 TF_REGISTRY_FUNCTION(TfEnum) {
212 TF_ADD_ENUM_NAME(TF_TEST_ERROR_1);
213 TF_ADD_ENUM_NAME(TF_TEST_ERROR_2);
214 }
215
mightRaise(bool raise)216 static void mightRaise(bool raise) {
217 if (raise) {
218 TF_ERROR(TF_TEST_ERROR_1, "Test error 1!");
219 TF_ERROR(TF_TEST_ERROR_2, "Test error 2!");
220 }
221 }
222
223
doErrors()224 static void doErrors() {
225 TF_ERROR(TF_TEST_ERROR_1, "TestError 1!");
226 TF_ERROR(TF_TEST_ERROR_2, "TestError 2!");
227 TF_CODING_ERROR("nonfatal coding error %d", 1);
228 TF_RUNTIME_ERROR("a random runtime error %d", 2);
229 TF_WARN("diagnostic warning %d", 3);
230 TF_STATUS("status message %d", 4);
231 };
232
233
234 struct _TestStaticMethodError {
Error_TestStaticMethodError235 static void Error() {
236 TF_ERROR(TF_TEST_ERROR_1, "Test error 1!");
237 }
238 };
239
240
241
242 ////////////////////////////////
243 // Enums
244
245 enum Tf_TestEnum {
246 Tf_Alpha = 3,
247 Tf_Bravo,
248 Tf_Charlie,
249 Tf_Delta,
250 };
251
252 enum class Tf_TestScopedEnum {
253 Hydrogen = 1,
254 Helium,
255 Lithium,
256 Beryllium,
257 Boron
258 };
259
260 struct Tf_Enum {
261 enum TestEnum2 {
262 One = 1,
263 Two,
264 Three,
265 };
266 enum TestEnum3 {
267 _Alpha = 100,
268 _Beta,
269 _Gamma,
270 };
271 enum class TestScopedEnum {
272 Alef = 300,
273 Bet,
274 Gimel
275 };
276 };
277
278
TF_REGISTRY_FUNCTION(TfEnum)279 TF_REGISTRY_FUNCTION(TfEnum) {
280 TF_ADD_ENUM_NAME(Tf_Alpha, "A");
281 TF_ADD_ENUM_NAME(Tf_Bravo, "B");
282 TF_ADD_ENUM_NAME(Tf_Charlie, "C");
283 TF_ADD_ENUM_NAME(Tf_Delta, "D");
284 }
285
TF_REGISTRY_FUNCTION(TfEnum)286 TF_REGISTRY_FUNCTION(TfEnum) {
287 TF_ADD_ENUM_NAME(Tf_Enum::One);
288 TF_ADD_ENUM_NAME(Tf_Enum::Two);
289 TF_ADD_ENUM_NAME(Tf_Enum::Three);
290 }
291
TF_REGISTRY_FUNCTION(TfEnum)292 TF_REGISTRY_FUNCTION(TfEnum) {
293 TF_ADD_ENUM_NAME(Tf_Enum::_Alpha);
294 TF_ADD_ENUM_NAME(Tf_Enum::_Beta);
295 TF_ADD_ENUM_NAME(Tf_Enum::_Gamma);
296 }
297
TF_REGISTRY_FUNCTION(TfEnum)298 TF_REGISTRY_FUNCTION(TfEnum) {
299 TF_ADD_ENUM_NAME(Tf_Enum::TestScopedEnum::Alef);
300 TF_ADD_ENUM_NAME(Tf_Enum::TestScopedEnum::Bet);
301 TF_ADD_ENUM_NAME(Tf_Enum::TestScopedEnum::Gimel);
302 }
303
TF_REGISTRY_FUNCTION(TfEnum)304 TF_REGISTRY_FUNCTION(TfEnum) {
305 TF_ADD_ENUM_NAME(Tf_TestScopedEnum::Hydrogen, "H");
306 TF_ADD_ENUM_NAME(Tf_TestScopedEnum::Lithium, "Li");
307 TF_ADD_ENUM_NAME(Tf_TestScopedEnum::Beryllium, "Be");
308 TF_ADD_ENUM_NAME(Tf_TestScopedEnum::Boron, "B");
309 }
310
takesTfEnum(TfEnum const & e)311 static void takesTfEnum(TfEnum const &e) {
312 printf("got enum '%s' with value '%d'\n",
313 TfEnum::GetName(e).c_str(), e.GetValueAsInt());
314 }
315
returnsTfEnum(TfEnum const & e)316 static TfEnum returnsTfEnum(TfEnum const &e) {
317 printf("returning enum '%s' with value '%d'\n",
318 TfEnum::GetName(e).c_str(), e.GetValueAsInt());
319 return e;
320 }
321
takesTestEnum(Tf_TestEnum e)322 static void takesTestEnum(Tf_TestEnum e) {
323 printf("got enum %d with name '%s'\n",
324 (int)e, TfEnum::GetName(e).c_str());
325 }
326
takesTestEnum2(Tf_Enum::TestEnum2 e)327 static void takesTestEnum2(Tf_Enum::TestEnum2 e) {
328 printf("got enum %d with name '%s'\n",
329 (int)e, TfEnum::GetName(e).c_str());
330 }
331
registerInvalidEnum(object & obj)332 static void registerInvalidEnum(object &obj) {
333 scope s = obj;
334
335 // This should be used to produce a coding error. The _Alpha value will
336 // conflict with the corresponding (sanitized) enum name that was already
337 // wrapped for Tf_TestEnum.
338 TfPyWrapEnum<Tf_Enum::TestEnum3>();
339 }
340
341
342
343 ////////////////////////////////
344 // Function callback stuff.
345
callback(std::function<void ()> const & f)346 static void callback(std::function<void ()> const &f) {
347 f();
348 }
349
stringCallback(std::function<string ()> const & f)350 static string stringCallback(std::function<string ()> const &f) {
351 return f();
352 }
353
stringStringCallback(std::function<string (string)> const & f)354 static string stringStringCallback(std::function<string (string)> const &f) {
355 return f("c++ is calling...");
356 }
357
callUnboundInstance(std::function<string (string)> const & f,string const & str)358 static string callUnboundInstance(std::function<string (string)> const &f,
359 string const &str) {
360 return f(str);
361 }
362
363 static TfStaticData<std::function<string ()> > _testCallback;
364
setTestCallback(std::function<string ()> const & func)365 static void setTestCallback(std::function<string ()> const &func) {
366 *_testCallback = func;
367 }
368
invokeTestCallback()369 static string invokeTestCallback() {
370 if (*_testCallback)
371 return (*_testCallback)();
372 return string();
373 }
374
375
376 ////////////////////////////////
377 // Sending notice from C++ sender
378
sendTfNoticeWithSender(Tf_TestBasePtr const & base)379 static void sendTfNoticeWithSender(Tf_TestBasePtr const &base) {
380 TfNotice().Send(base);
381 }
382
383 ////////////////////////////////
384 // TfPyClassMethod()
385
386 class Tf_ClassWithClassMethod {
387 public:
Tf_ClassWithClassMethod()388 Tf_ClassWithClassMethod() {}
~Tf_ClassWithClassMethod()389 virtual ~Tf_ClassWithClassMethod() {}
390 };
391
392 static tuple
_TestClassMethod(object & pyClassObj,const object & callable)393 _TestClassMethod( object & pyClassObj, const object & callable )
394 {
395 return boost::python::make_tuple(
396 pyClassObj, TfPyCall<object>(callable)() );
397 }
398
399 // ////////////////////////////////
400 // // keywords and overloading.
401
402
403 // static void f1(string const &a1, int x, int y) {
404 // printf("f1 with %s, %d, %d\n", a1.c_str(), x, y);
405 // }
406
407 // static void f2(string const &a1, string const &a2, int x, int y) {
408 // printf("f2 with %s, %s, %d, %d\n", a1.c_str(), a2.c_str(), x, y);
409 // }
410
411 static std::string
_ThrowCppException()412 _ThrowCppException()
413 {
414 // Take the lock.
415 TfPyLock lock;
416 // Release the lock.
417 lock.BeginAllowThreads();
418 // Generate an exception.
419 throw std::logic_error("error");
420 // Not necessary, but shows usage.
421 lock.EndAllowThreads();
422 return std::string();
423 }
424
TakesVecVecString(std::vector<std::vector<std::string>> arg)425 static size_t TakesVecVecString(std::vector<std::vector<std::string> > arg)
426 {
427 return arg.size();
428 }
429
430 ////////////////////////////////
431 // TfPyArg and TfMakeConstructorWithVarArgs
432
433 TF_DECLARE_WEAK_AND_REF_PTRS(Tf_ClassWithVarArgInit);
434
435 class Tf_ClassWithVarArgInit : public TfRefBase, public TfWeakBase
436 {
437 public:
438 bool allowExtraArgs;
439 tuple args;
440 dict kwargs;
441 };
442
443 static Tf_ClassWithVarArgInitRefPtr
_MakeClassWithVarArgInit(bool allowExtraArgs,const tuple & args,const dict & kwargs)444 _MakeClassWithVarArgInit(bool allowExtraArgs,
445 const tuple& args, const dict& kwargs)
446 {
447 // To Python consumer, this class has 3 explicit optional arguments, named
448 // 'a', 'b', and 'c'.
449 const TfPyArgs optionalArgs = boost::assign::list_of<>
450 (TfPyArg("a", ""))
451 (TfPyArg("b", ""))
452 (TfPyArg("c", ""));
453
454 const std::pair<tuple, dict> params =
455 TfPyProcessOptionalArgs(args, kwargs, optionalArgs, allowExtraArgs);
456
457 Tf_ClassWithVarArgInitRefPtr rval =
458 TfCreateRefPtr(new Tf_ClassWithVarArgInit);
459 rval->allowExtraArgs = allowExtraArgs;
460 rval->args = params.first;
461 rval->kwargs = params.second;
462
463 return rval;
464 }
465
466
467 ////////////////////////////////
468 // Bytearray conversion
469
470 static object
_ConvertByteListToByteArray(const list & byteList)471 _ConvertByteListToByteArray(const list& byteList)
472 {
473 std::vector<char> inputList;
474 for (int i = 0; i < len(byteList); ++i) {
475 inputList.push_back(extract<char>(byteList[i]));
476 }
477
478 return TfPyCopyBufferToByteArray(inputList.data(), inputList.size());
479 }
480
481
482 PXR_NAMESPACE_CLOSE_SCOPE
483
wrapTf_TestTfPython()484 void wrapTf_TestTfPython()
485 {
486
487 // def("f", f1, (arg("x")=3, arg("y")=4));
488 // def("f", f2, (arg("x")=5, arg("y")=6));
489
490 def("_ConvertByteListToByteArray", _ConvertByteListToByteArray);
491
492 def("_sendTfNoticeWithSender", sendTfNoticeWithSender);
493
494 def("_callback", callback);
495 def("_stringCallback", stringCallback);
496 TfPyFunctionFromPython<string (string)>();
497 def("_stringStringCallback", stringStringCallback);
498 def("_setTestCallback", setTestCallback);
499 def("_invokeTestCallback", invokeTestCallback);
500 def("_callUnboundInstance", callUnboundInstance);
501
502 TfPyWrapEnum<Tf_TestEnum>();
503
504 {
505 scope enumScope = class_<Tf_Enum>("_Enum", no_init);
506 TfPyWrapEnum<Tf_Enum::TestEnum2>();
507 TfPyWrapEnum<Tf_Enum::TestScopedEnum>();
508 }
509
510 TfPyWrapEnum<Tf_TestScopedEnum>();
511
512 def("_takesTfEnum", takesTfEnum);
513 def("_returnsTfEnum", returnsTfEnum);
514 def("_takesTestEnum", takesTestEnum);
515 def("_takesTestEnum2", takesTestEnum2);
516 def("_registerInvalidEnum", registerInvalidEnum);
517
518
519 def("_doErrors", doErrors);
520
521 def("_mightRaise", mightRaise);
522
523 def("_ThrowCppException", _ThrowCppException);
524
525 def("_TakesVecVecString", TakesVecVecString);
526
527 class_<_TestStaticMethodError>("_TestStaticMethodError", no_init)
528 .def("Error", &_TestStaticMethodError::Error)
529 .staticmethod("Error")
530 ;
531
532 def("_TakesReference", TakesReference);
533 def("_TakesConstBase", TakesConstBase);
534 def("_ReturnsConstBase", ReturnsConstBase);
535 def("_TakesBase", TakesBase);
536 def("_ReturnsBase", ReturnsBase);
537 def("_ReturnsBaseRefPtr", ReturnsBaseRefPtr);
538 def("_TakesDerived", TakesDerived);
539
540 def("_DerivedFactory", Tf_TestDerived::Factory,
541 return_value_policy<TfPyRefPtrFactory<> >());
542
543 def("_DerivedNullFactory", Tf_TestDerived::NullFactory,
544 return_value_policy<TfPyRefPtrFactory<> >());
545
546 class_<polymorphic_Tf_TestBase<>,
547 TfWeakPtr<polymorphic_Tf_TestBase<> >, boost::noncopyable>
548 ("_TestBase", no_init)
549 .def(TfPyRefAndWeakPtr())
550 .def(TfMakePyConstructor(__Ref_init__<polymorphic_Tf_TestBase<> >))
551 .def("Virtual", pure_virtual(&Tf_TestBase::Virtual))
552 .def("Virtual2", pure_virtual(&Tf_TestBase::Virtual2))
553 .def("Virtual3", pure_virtual(&Tf_TestBase::Virtual3))
554 .def("Virtual4", &Tf_TestBase::Virtual4,
555 &polymorphic_Tf_TestBase<>::default_Virtual4)
556 .def("TestCallVirtual", &callVirtual)
557 ;
558
559 class_<polymorphic_Tf_TestDerived<>,
560 TfWeakPtr<polymorphic_Tf_TestDerived<> >,
561 bases<Tf_TestBase>, boost::noncopyable>
562 ("_TestDerived", no_init)
563 .def(TfPyRefAndWeakPtr())
564 .def("__init__",
565 TfMakePyConstructor(__Ref_init__<polymorphic_Tf_TestDerived<> >))
566 .def("Virtual", &Tf_TestDerived::Virtual,
567 &polymorphic_Tf_TestDerived<>::default_Virtual)
568 .def("Virtual2", &Tf_TestDerived::Virtual2,
569 &polymorphic_Tf_TestDerived<>::default_Virtual2)
570 .def("Virtual3", &Tf_TestDerived::Virtual3,
571 &polymorphic_Tf_TestDerived<>::default_Virtual3)
572 ;
573
574 class_<Tf_ClassWithClassMethod>("_ClassWithClassMethod", init<>() )
575 .def("Test", &_TestClassMethod)
576 .def(TfPyClassMethod("Test"))
577 ;
578
579 class_<Tf_ClassWithVarArgInit, Tf_ClassWithVarArgInitPtr>
580 ("_ClassWithVarArgInit", no_init)
581 .def(TfPyRefAndWeakPtr())
582 .def(TfMakePyConstructorWithVarArgs(&_MakeClassWithVarArgInit))
583 .add_property("allowExtraArgs",
584 &Tf_ClassWithVarArgInit::allowExtraArgs)
585 .add_property("args", &Tf_ClassWithVarArgInit::args)
586 .add_property("kwargs", &Tf_ClassWithVarArgInit::kwargs)
587 ;
588
589 }
590
591 TF_REFPTR_CONST_VOLATILE_GET(Tf_ClassWithVarArgInit)
592 TF_REFPTR_CONST_VOLATILE_GET(Tf_TestBase)
593 TF_REFPTR_CONST_VOLATILE_GET(Tf_TestDerived)
594 TF_REFPTR_CONST_VOLATILE_GET(polymorphic_Tf_TestBase<class Tf_TestBase>)
595 TF_REFPTR_CONST_VOLATILE_GET(polymorphic_Tf_TestDerived<class Tf_TestDerived>)
596