1
0

module.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #include "test.h"
  2. #include <gtest/gtest.h>
  3. PYBIND11_EMBEDDED_MODULE(example, m) {
  4. m.def("add", [](int a, int b) {
  5. return a + b;
  6. });
  7. auto math = m.def_submodule("math");
  8. math.def("sub", [](int a, int b) {
  9. return a - b;
  10. });
  11. }
  12. PYBIND11_MODULE(example3, m) {
  13. m.def("add", [](int a, int b) {
  14. return a + b;
  15. });
  16. auto math = m.def_submodule("math");
  17. math.def("sub", [](int a, int b) {
  18. return a - b;
  19. });
  20. }
  21. namespace {
  22. TEST_F(PYBIND11_TEST, module) {
  23. py::exec("import example");
  24. EXPECT_EVAL_EQ("example.add(1, 2)", 3);
  25. py::exec("from example import math");
  26. EXPECT_EVAL_EQ("math.sub(1, 2)", -1);
  27. py::exec("from example.math import sub");
  28. EXPECT_EVAL_EQ("sub(1, 2)", -1);
  29. auto math = py::module::import("example.math");
  30. EXPECT_EQ(math.attr("sub")(4, 3).cast<int>(), 1);
  31. }
  32. TEST_F(PYBIND11_TEST, raw_module) {
  33. auto m = py::module::create("example2");
  34. m.def("add", [](int a, int b) {
  35. return a + b;
  36. });
  37. auto math = m.def_submodule("math");
  38. math.def("sub", [](int a, int b) {
  39. return a - b;
  40. });
  41. py::exec("import example2");
  42. EXPECT_EVAL_EQ("example2.add(1, 2)", 3);
  43. py::exec("from example2 import math");
  44. EXPECT_EVAL_EQ("math.sub(1, 2)", -1);
  45. py::exec("from example2.math import sub");
  46. EXPECT_EVAL_EQ("sub(1, 2)", -1);
  47. auto math2 = py::module::import("example2.math");
  48. EXPECT_EQ(math2.attr("sub")(4, 3).cast<int>(), 1);
  49. }
  50. TEST_F(PYBIND11_TEST, dynamic_module) {
  51. py_module_initialize();
  52. py::exec("import example3");
  53. EXPECT_EVAL_EQ("example3.add(1, 2)", 3);
  54. py::exec("from example3 import math");
  55. EXPECT_EVAL_EQ("math.sub(1, 2)", -1);
  56. py::exec("from example3.math import sub");
  57. EXPECT_EVAL_EQ("sub(1, 2)", -1);
  58. auto math = py::module::import("example3.math");
  59. EXPECT_EQ(math.attr("sub")(4, 3).cast<int>(), 1);
  60. }
  61. struct import_callback {
  62. using cb_type = decltype(py_callbacks()->importfile);
  63. import_callback() {
  64. assert(_importfile == nullptr);
  65. _importfile = py_callbacks()->importfile;
  66. py_callbacks()->importfile = importfile;
  67. };
  68. ~import_callback() {
  69. assert(_importfile != nullptr);
  70. py_callbacks()->importfile = _importfile;
  71. _importfile = nullptr;
  72. };
  73. static char* importfile(const char* path, int* data_size) {
  74. if(value.empty()) return _importfile(path, data_size);
  75. // +1 for the null terminator
  76. char* cstr = new char[value.size() + 1];
  77. std::strcpy(cstr, value.c_str());
  78. return cstr;
  79. }
  80. static std::string value;
  81. private:
  82. static cb_type _importfile;
  83. };
  84. import_callback::cb_type import_callback::_importfile = nullptr;
  85. std::string import_callback::value = "";
  86. TEST_F(PYBIND11_TEST, reload_module) {
  87. import_callback cb;
  88. import_callback::value = "value = 1\n";
  89. auto mod = py::module::import("reload_module");
  90. EXPECT_EQ(mod.attr("value").cast<int>(), 1);
  91. import_callback::value = "value = 2\n";
  92. mod.reload();
  93. EXPECT_EQ(mod.attr("value").cast<int>(), 2);
  94. import_callback::value = "raise ValueError()";
  95. // Reload in Python raises a ValueError
  96. py::exec(
  97. "import importlib\nimport reload_module\ntry:\n importlib.reload(reload_module)\nexcept ValueError:\n pass");
  98. // Reload in C++ raises a ValueError
  99. try {
  100. mod.reload();
  101. } catch(py::error_already_set& e) {
  102. if(e.match(tp_ValueError)) { return; }
  103. std::rethrow_exception(std::current_exception());
  104. }
  105. }
  106. } // namespace