From 12ce725edbe6d9dc128175a5d5342b1fc28d495e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CDen=E2=80=9D?= Date: Sat, 27 Apr 2024 17:32:06 +0300 Subject: [PATCH 1/6] fix Var::toDouble() type casting handling --- cppy3/cppy3.cpp | 4 ++-- cppy3/cppy3.hpp | 8 +++++++- tests/tests.cpp | 27 ++++++++++++++++++++++++--- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/cppy3/cppy3.cpp b/cppy3/cppy3.cpp index df545be..901e740 100644 --- a/cppy3/cppy3.cpp +++ b/cppy3/cppy3.cpp @@ -28,7 +28,7 @@ namespace cppy3 // initialize GIL PyEval_InitThreads(); } - + PythonVM::PythonVM(const std::string &name, ModuleInitializer module) { @@ -383,7 +383,7 @@ namespace cppy3 double Var::toDouble() const { - long value = 0; + double value = 0; extract(_o, value); return value; } diff --git a/cppy3/cppy3.hpp b/cppy3/cppy3.hpp index 789ec51..c6a9c7c 100644 --- a/cppy3/cppy3.hpp +++ b/cppy3/cppy3.hpp @@ -495,7 +495,13 @@ namespace cppy3 template void getVar(const std::wstring &varName, T &value) const { - PyObject *o = PyDict_GetItemString(*this, WideToUTF8(varName).data()); + getVar(WideToUTF8(varName), value); + } + + template + void getVar(const std::string &varName, T &value) const + { + PyObject *o = PyDict_GetItemString(*this, varName.data()); assert(o); extract(o, value); } diff --git a/tests/tests.cpp b/tests/tests.cpp index 58b806d..b859f77 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -43,22 +43,43 @@ TEST_CASE( "Utils", "" ) { } } -TEST_CASE( "cppy3 public functionality", "main funcs" ) { +TEST_CASE( "cppy3: Embedding Python into C++ code", "main funcs" ) { // create interpreter cppy3::PythonVM instance; SECTION("c++ -> python -> c++ variables injection/extraction") { - // inject + + // inject C++ -> python cppy3::Main().injectVar("a", 2); cppy3::Main().injectVar("b", 2); cppy3::exec("assert a + b == 4"); cppy3::exec("print('sum is', a + b)"); - // extract + + // extract python -> C++ const cppy3::Var sum = cppy3::eval("a + b"); REQUIRE(sum.type() == cppy3::Var::LONG); REQUIRE(sum.toLong() == 4); REQUIRE(sum.toString() == L"4"); REQUIRE(!cppy3::error()); + + try { + // extract casting integer as double is forbidden + sum.toDouble(); + REQUIRE(false); // unreachable code, expect an exception + } catch (const cppy3::PythonException& e) { + REQUIRE(e.info.reason == L"variable is not a real type"); + } + + // python var assign name from c++ -> python + cppy3::Main().inject("sum_var", sum); + cppy3::exec("assert sum_var == 4"); + + // cast to float in python + cppy3::eval("sum_var = float(sum_var)"); + // can extract in c++ as double + double sum_var = 0; + cppy3::Main().getVar("sum_var", sum_var); + REQUIRE(abs(sum_var - 4.0) < 10e-10); } SECTION("python -> c++ exception forwarding") { From 3ae6dacc3f1c1e78c4be464296c990ee25f8b135 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CDen=E2=80=9D?= Date: Sat, 27 Apr 2024 17:32:26 +0300 Subject: [PATCH 2/6] fix github CI MACOS env --- .github/workflows/cmake-multi-platform.yml | 2 +- .gitignore | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index a022363..8745000 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -60,7 +60,7 @@ jobs: - name: MACOS numpy build depencency if: matrix.os == 'macos-latest' run: | - python3 -m pip install numpy + python3 -m pip install --user --break-system-packages numpy - name: Set reusable strings # Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file. diff --git a/.gitignore b/.gitignore index baf33b8..df475a3 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,5 @@ CMakeLists.txt.user build .vscode + +/.DS_Store From 08c3e959187244b9eed5851b4c40c16a44dc298a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CDen=E2=80=9D?= Date: Sat, 27 Apr 2024 17:39:10 +0300 Subject: [PATCH 3/6] exclude OSX + GCC build from CI --- .github/workflows/cmake-multi-platform.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 8745000..773a53a 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -48,6 +48,8 @@ jobs: c_compiler: cl - os: macos-latest c_compiler: cl + - os: macos-latest + c_compiler: gcc steps: - uses: actions/checkout@v3 From eac4904bb56673940fcf800bd717a2bcbf5bff5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CDen=E2=80=9D?= Date: Sat, 27 Apr 2024 18:10:40 +0300 Subject: [PATCH 4/6] WINDOWS numpy build depencency --- .github/workflows/cmake-multi-platform.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 773a53a..077f49b 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -26,6 +26,8 @@ jobs: os: [ubuntu-latest, macos-latest, windows-latest] build_type: [Release, Debug] c_compiler: [gcc, clang, cl] + python-version: ["3.10"] + include: - os: windows-latest c_compiler: cl @@ -64,6 +66,11 @@ jobs: run: | python3 -m pip install --user --break-system-packages numpy + - name: WINDOWS numpy build depencency + if: matrix.os == 'windows-latest' + run: | + python3 -m pip install --user numpy + - name: Set reusable strings # Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file. id: strings From e9491e3b3b2bf8a63c454676cf4a311acfa729cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CDen=E2=80=9D?= Date: Sat, 27 Apr 2024 18:16:03 +0300 Subject: [PATCH 5/6] WINDOWS numpy build depencency --- .github/workflows/cmake-multi-platform.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cmake-multi-platform.yml b/.github/workflows/cmake-multi-platform.yml index 077f49b..f9e838b 100644 --- a/.github/workflows/cmake-multi-platform.yml +++ b/.github/workflows/cmake-multi-platform.yml @@ -69,7 +69,7 @@ jobs: - name: WINDOWS numpy build depencency if: matrix.os == 'windows-latest' run: | - python3 -m pip install --user numpy + python3 -m pip install numpy - name: Set reusable strings # Turn repeated input strings (such as the build output directory) into step outputs. These step outputs can be used throughout the workflow file. From 994d86c3ef77be19ded5b7cb23fb484627ac44f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CDen=E2=80=9D?= Date: Sat, 27 Apr 2024 19:24:25 +0300 Subject: [PATCH 6/6] remove deprecated C API PyUnicode_AsUnicode() for support python 3.12 OSX Clang 15 --- cppy3/cppy3.cpp | 10 +++++++++- tests/tests.cpp | 13 +++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/cppy3/cppy3.cpp b/cppy3/cppy3.cpp index 901e740..f0a58b0 100644 --- a/cppy3/cppy3.cpp +++ b/cppy3/cppy3.cpp @@ -320,7 +320,15 @@ namespace cppy3 throw PythonException(L"variable has no string representation"); } } - value = PyUnicode_AsUnicode(str); + + Py_ssize_t size; + wchar_t* wideCharStr = PyUnicode_AsWideCharString(str, &size); + if (wideCharStr != NULL) { + const std::wstring wstr(wideCharStr, size); + value = wstr; + PyMem_Free(wideCharStr); + } + } void extract(PyObject *o, double &value) diff --git a/tests/tests.cpp b/tests/tests.cpp index b859f77..35cad48 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -80,6 +80,19 @@ TEST_CASE( "cppy3: Embedding Python into C++ code", "main funcs" ) { double sum_var = 0; cppy3::Main().getVar("sum_var", sum_var); REQUIRE(abs(sum_var - 4.0) < 10e-10); + + // unicode strings inject / extract via exec / eval + const std::wstring unicodeStr = L"юникод smile ☺"; + cppy3::exec(L"uu = '" + unicodeStr + L"'"); + const cppy3::Var uVar = cppy3::eval("uu"); + REQUIRE(uVar.toString() == unicodeStr); + + // unicode string inject / extract via converters + cppy3::Main().injectVar("uVar2", unicodeStr); + cppy3::exec("print('uVar2:', uVar2)"); + std::wstring uVar2; + cppy3::Main().getVar("uVar2", uVar2); + REQUIRE(uVar2 == unicodeStr); } SECTION("python -> c++ exception forwarding") {