Callable.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // Copyright (c) 2013-2018 Josh Blum
  2. // SPDX-License-Identifier: BSL-1.0
  3. #include <Pothos/Callable/CallableImpl.hpp>
  4. #include <Pothos/Callable/Exception.hpp>
  5. #include <Pothos/Object/Exception.hpp>
  6. #include <Pothos/Util/TypeInfo.hpp>
  7. #include <Poco/Format.h>
  8. #include <cassert>
  9. #include <algorithm> //min/max
  10. Pothos::Callable::Callable(void)
  11. {
  12. assert(not *this);
  13. }
  14. Pothos::Object Pothos::Callable::opaqueCall(const Object *inputArgs, const size_t numArgs) const
  15. {
  16. if (_impl == nullptr)
  17. {
  18. throw Pothos::CallableNullError("Pothos::Callable::call()", "null Callable");
  19. }
  20. //Create callArgs which is a combination of inputArgs and boundArgs
  21. std::vector<Object> callArgs(_impl->getNumArgs());
  22. size_t inputArgsIndex = 0;
  23. for (size_t i = 0; i < callArgs.size(); i++)
  24. {
  25. //is there a binding? if so use it
  26. if (_boundArgs.size() > i and _boundArgs[i])
  27. {
  28. callArgs[i] = _boundArgs[i];
  29. }
  30. //otherwise, use the next available input argument
  31. else
  32. {
  33. if (numArgs <= inputArgsIndex)
  34. {
  35. throw Pothos::CallableArgumentError("Pothos::Callable::call()", Poco::format(
  36. "expected input argument at %z", inputArgsIndex));
  37. }
  38. callArgs[i] = inputArgs[inputArgsIndex++];
  39. }
  40. //perform conversion on arg to get an Object of the exact type
  41. try
  42. {
  43. callArgs[i] = callArgs[i].convert(_impl->type(int(i)));
  44. }
  45. catch(const Pothos::ObjectConvertError &ex)
  46. {
  47. throw Pothos::CallableArgumentError("Pothos::Callable::call()", Poco::format(
  48. "failed to convert arg%z\n%s", i, std::string(ex.displayText())));
  49. }
  50. }
  51. return _impl->call(callArgs.data());
  52. }
  53. size_t Pothos::Callable::getNumArgs(void) const
  54. {
  55. if (_impl == nullptr)
  56. {
  57. throw Pothos::CallableNullError("Pothos::Callable::getNumArgs()", "null Callable");
  58. }
  59. size_t numArgs = _impl->getNumArgs();
  60. //remove bound args from the count
  61. for (size_t i = 0; i < std::min(_impl->getNumArgs(), _boundArgs.size()); i++)
  62. {
  63. if (_boundArgs[i]) numArgs--;
  64. }
  65. return numArgs;
  66. }
  67. const std::type_info &Pothos::Callable::type(const int argNo) const
  68. {
  69. if (_impl == nullptr)
  70. {
  71. throw Pothos::CallableNullError("Pothos::Callable::type()", "null Callable");
  72. }
  73. if (argNo < -1)
  74. {
  75. throw Pothos::CallableArgumentError("Pothos::Callable::type()", Poco::format(
  76. "unexpected argNo %d", argNo));
  77. }
  78. if (argNo >= int(this->getNumArgs()))
  79. {
  80. throw Pothos::CallableArgumentError("Pothos::Callable::type()", Poco::format(
  81. "unexpected argNo %d but call takes %z arguments", argNo, this->getNumArgs()));
  82. }
  83. if (argNo == -1) return _impl->type(-1);
  84. //add bound args into the actual arg number
  85. int skippedIndexes = 0;
  86. for (size_t i = 0; i < _boundArgs.size(); i++)
  87. {
  88. if (_boundArgs[i]) skippedIndexes++;
  89. else if (int(i) == argNo + skippedIndexes) break;
  90. }
  91. return _impl->type(argNo + skippedIndexes);
  92. }
  93. Pothos::Callable &Pothos::Callable::bind(Object &&val, const size_t argNo)
  94. {
  95. if (_boundArgs.size() <= argNo) _boundArgs.resize(argNo+1);
  96. _boundArgs[argNo] = val;
  97. return *this;
  98. }
  99. Pothos::Callable &Pothos::Callable::unbind(const size_t argNo)
  100. {
  101. return this->bind(Object(), argNo);
  102. }
  103. std::string Pothos::Callable::toString(void) const
  104. {
  105. if (_impl == nullptr) return "null";
  106. std::string output;
  107. output += Util::typeInfoToString(this->type(-1));
  108. output += "(";
  109. for (size_t i = 0; i < this->getNumArgs(); i++)
  110. {
  111. if (i != 0) output += ", ";
  112. output += Util::typeInfoToString(this->type(int(i)));
  113. }
  114. output += ")";
  115. return output;
  116. }
  117. Pothos::Detail::CallableContainer::CallableContainer(void)
  118. {
  119. return;
  120. }
  121. Pothos::Detail::CallableContainer::~CallableContainer(void)
  122. {
  123. return;
  124. }
  125. Pothos::Callable::operator bool(void) const
  126. {
  127. return bool(_impl);
  128. }
  129. bool Pothos::operator==(const Callable &lhs, const Callable &rhs)
  130. {
  131. return (lhs._impl == rhs._impl) and (lhs._boundArgs == rhs._boundArgs);
  132. }
  133. #include <Pothos/Managed.hpp>
  134. static auto managedCallable = Pothos::ManagedClass()
  135. .registerConstructor<Pothos::Callable>()
  136. .registerOpaqueMethod("()", &Pothos::Callable::opaqueCall)
  137. .commit("Pothos/Callable");