Skip to content

Commit

Permalink
Merge pull request #4 from reefactor/fix-build
Browse files Browse the repository at this point in the history
Fix Var::toDouble() type casting handling & Fix OSX CI github tests by
removing deprecated C API PyUnicode_AsUnicode() for support python 3.12
  • Loading branch information
reefactor authored Apr 27, 2024
2 parents 9606923 + 994d86c commit c099bb2
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 7 deletions.
9 changes: 9 additions & 0 deletions .github/workflows/cmake-multi-platform.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -48,6 +50,8 @@ jobs:
c_compiler: cl
- os: macos-latest
c_compiler: cl
- os: macos-latest
c_compiler: gcc

steps:
- uses: actions/checkout@v3
Expand All @@ -59,6 +63,11 @@ jobs:
- name: MACOS numpy build depencency
if: matrix.os == 'macos-latest'
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 numpy
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,5 @@
CMakeLists.txt.user
build
.vscode

/.DS_Store
14 changes: 11 additions & 3 deletions cppy3/cppy3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ namespace cppy3
// initialize GIL
PyEval_InitThreads();
}

PythonVM::PythonVM(const std::string &name, ModuleInitializer module)
{

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -383,7 +391,7 @@ namespace cppy3

double Var::toDouble() const
{
long value = 0;
double value = 0;
extract(_o, value);
return value;
}
Expand Down
8 changes: 7 additions & 1 deletion cppy3/cppy3.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,13 @@ namespace cppy3
template <typename T>
void getVar(const std::wstring &varName, T &value) const
{
PyObject *o = PyDict_GetItemString(*this, WideToUTF8(varName).data());
getVar(WideToUTF8(varName), value);
}

template <typename T>
void getVar(const std::string &varName, T &value) const
{
PyObject *o = PyDict_GetItemString(*this, varName.data());
assert(o);
extract(o, value);
}
Expand Down
40 changes: 37 additions & 3 deletions tests/tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,56 @@ 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<int>("a", 2);
cppy3::Main().injectVar<int>("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<double>("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<std::wstring>("uVar2", unicodeStr);
cppy3::exec("print('uVar2:', uVar2)");
std::wstring uVar2;
cppy3::Main().getVar<std::wstring>("uVar2", uVar2);
REQUIRE(uVar2 == unicodeStr);
}

SECTION("python -> c++ exception forwarding") {
Expand Down

0 comments on commit c099bb2

Please sign in to comment.