diff --git a/PythonConvert.cpp b/PythonConvert.cpp index 54fd24a..b3894ba 100644 --- a/PythonConvert.cpp +++ b/PythonConvert.cpp @@ -1,13 +1,31 @@ // Copyright (c) 2013-2016 Josh Blum +// 2019 Nicholas Corgan // SPDX-License-Identifier: BSL-1.0 #include #include #include #include +#include +#include #include #include "PythonProxy.hpp" +/*********************************************************************** + * SFINAE typedefs + **********************************************************************/ +template +using EnableIfUnsigned = typename std::enable_if::value && (sizeof(T) < 8), U>::type; + +template +using EnableIfSigned = typename std::enable_if::value && (sizeof(T) < 8), U>::type; + +template +using EnableIfUnsigned64 = typename std::enable_if::value && (sizeof(T) == 8), U>::type; + +template +using EnableIfSigned64 = typename std::enable_if::value && (sizeof(T) == 8), U>::type; + /*********************************************************************** * Object -- Allow the use of native python objects. * @@ -70,10 +88,10 @@ pothos_static_block(pothosRegisterPythonBoolConversions) } /*********************************************************************** - * integer types + * integer/long types **********************************************************************/ template -static Pothos::Proxy convertIntNumToPyInt(Pothos::ProxyEnvironment::Sptr env, const T &num) +static EnableIfSigned convertIntNumToPyNum(Pothos::ProxyEnvironment::Sptr env, const T &num) { #if PY_MAJOR_VERSION >= 3 return std::dynamic_pointer_cast(env)->makeHandle(PyLong_FromLong(long(num)), REF_NEW); @@ -82,6 +100,28 @@ static Pothos::Proxy convertIntNumToPyInt(Pothos::ProxyEnvironment::Sptr env, co #endif } +template +static EnableIfUnsigned convertIntNumToPyNum(Pothos::ProxyEnvironment::Sptr env, const T &num) +{ + #if PY_MAJOR_VERSION >= 3 + return std::dynamic_pointer_cast(env)->makeHandle(PyLong_FromUnsignedLong((unsigned long)(num)), REF_NEW); + #else + return std::dynamic_pointer_cast(env)->makeHandle(PyInt_FromUnsignedLong((unsigned long)(num)), REF_NEW); + #endif +} + +template +static EnableIfSigned64 convertIntNumToPyNum(Pothos::ProxyEnvironment::Sptr env, const T &num) +{ + return std::dynamic_pointer_cast(env)->makeHandle(PyLong_FromLongLong((long long)num), REF_NEW); +} + +template +static EnableIfUnsigned64 convertIntNumToPyNum(Pothos::ProxyEnvironment::Sptr env, const T &num) +{ + return std::dynamic_pointer_cast(env)->makeHandle(PyLong_FromUnsignedLongLong((unsigned long long)num), REF_NEW); +} + static long long convertPyIntToLongLong(const Pothos::Proxy &proxy) { //python3 has only PyLong functions and we always convert to long long @@ -101,57 +141,37 @@ static long long convertPyIntToLongLong(const Pothos::Proxy &proxy) pothos_static_block(pothosRegisterPythonIntConversions) { - Pothos::PluginRegistry::addCall("/proxy/converters/python/char_to_pyint", - &convertIntNumToPyInt); - Pothos::PluginRegistry::addCall("/proxy/converters/python/schar_to_pyint", - &convertIntNumToPyInt); - Pothos::PluginRegistry::addCall("/proxy/converters/python/uchar_to_pyint", - &convertIntNumToPyInt); - - Pothos::PluginRegistry::addCall("/proxy/converters/python/sshort_to_pyint", - &convertIntNumToPyInt); - Pothos::PluginRegistry::addCall("/proxy/converters/python/ushort_to_pyint", - &convertIntNumToPyInt); - - Pothos::PluginRegistry::addCall("/proxy/converters/python/sint_to_pyint", - &convertIntNumToPyInt); - Pothos::PluginRegistry::addCall("/proxy/converters/python/uint_to_pyint", - &convertIntNumToPyInt); - - Pothos::PluginRegistry::addCall("/proxy/converters/python/slong_to_pyint", - &convertIntNumToPyInt); - Pothos::PluginRegistry::addCall("/proxy/converters/python/ulong_to_pyint", - &convertIntNumToPyInt); + Pothos::PluginRegistry::addCall("/proxy/converters/python/char_to_pynum", + &convertIntNumToPyNum); + Pothos::PluginRegistry::addCall("/proxy/converters/python/schar_to_pynum", + &convertIntNumToPyNum); + Pothos::PluginRegistry::addCall("/proxy/converters/python/uchar_to_pynum", + &convertIntNumToPyNum); + + Pothos::PluginRegistry::addCall("/proxy/converters/python/sshort_to_pynum", + &convertIntNumToPyNum); + Pothos::PluginRegistry::addCall("/proxy/converters/python/ushort_to_pynum", + &convertIntNumToPyNum); + + Pothos::PluginRegistry::addCall("/proxy/converters/python/sint_to_pynum", + &convertIntNumToPyNum); + Pothos::PluginRegistry::addCall("/proxy/converters/python/uint_to_pynum", + &convertIntNumToPyNum); + + Pothos::PluginRegistry::addCall("/proxy/converters/python/slong_to_pynum", + &convertIntNumToPyNum); + Pothos::PluginRegistry::addCall("/proxy/converters/python/ulong_to_pynum", + &convertIntNumToPyNum); + + Pothos::PluginRegistry::addCall("/proxy/converters/python/sllong_to_pynum", + &convertIntNumToPyNum); + Pothos::PluginRegistry::addCall("/proxy/converters/python/ullong_to_pynum", + &convertIntNumToPyNum); Pothos::PluginRegistry::add("/proxy/converters/python/pyint_to_llong", Pothos::ProxyConvertPair("int", &convertPyIntToLongLong)); } -/*********************************************************************** - * long types - **********************************************************************/ -template -static Pothos::Proxy convertLongLongToPyLong(Pothos::ProxyEnvironment::Sptr env, const T &num) -{ - return std::dynamic_pointer_cast(env)->makeHandle(PyLong_FromLongLong((long long)(num)), REF_NEW); -} - -static long long convertPyLongToLongLong(const Pothos::Proxy &proxy) -{ - return PyLong_AsLongLong(std::dynamic_pointer_cast(proxy.getHandle())->obj); -} - -pothos_static_block(pothosRegisterPythonLongConversions) -{ - Pothos::PluginRegistry::addCall("/proxy/converters/python/sllong_to_pylong", - &convertLongLongToPyLong); - Pothos::PluginRegistry::addCall("/proxy/converters/python/ullong_to_pylong", - &convertLongLongToPyLong); - - Pothos::PluginRegistry::add("/proxy/converters/python/pylong_to_llong", - Pothos::ProxyConvertPair("long", &convertPyLongToLongLong)); -} - /*********************************************************************** * float types **********************************************************************/ diff --git a/TestPython.cpp b/TestPython.cpp index d0095b6..da0034c 100644 --- a/TestPython.cpp +++ b/TestPython.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2013-2017 Josh Blum +// 2019 Nicholas Corgan // SPDX-License-Identifier: BSL-1.0 #include @@ -9,6 +10,7 @@ #include #include #include +#include POTHOS_TEST_BLOCK("/proxy/python/tests", test_basic_types) { @@ -37,6 +39,36 @@ POTHOS_TEST_BLOCK("/proxy/python/tests", test_basic_types) POTHOS_TEST_EQUAL(env->makeProxy(strVal).convert(), strVal); } +template +static void testTypeBounds(Pothos::ProxyEnvironment::Sptr env) +{ + const T minVal = std::numeric_limits::min(); + POTHOS_TEST_EQUAL(env->makeProxy(minVal).template convert(), minVal); + + const T maxVal = std::numeric_limits::max(); + POTHOS_TEST_EQUAL(env->makeProxy(maxVal).template convert(), maxVal); +} + +POTHOS_TEST_BLOCK("/proxy/python/tests", test_basic_type_bounds) +{ + auto env = Pothos::ProxyEnvironment::make("python"); + + testTypeBounds(env); + testTypeBounds(env); + testTypeBounds(env); + testTypeBounds(env); + testTypeBounds(env); + + testTypeBounds(env); + testTypeBounds(env); + testTypeBounds(env); + testTypeBounds(env); + testTypeBounds(env); + + testTypeBounds(env); + testTypeBounds(env); +} + POTHOS_TEST_BLOCK("/proxy/python/tests", test_compare_to) { auto env = Pothos::ProxyEnvironment::make("python"); @@ -189,8 +221,16 @@ POTHOS_TEST_BLOCK("/proxy/python/tests", test_numpy_types) auto env = Pothos::ProxyEnvironment::make("python"); auto numpy = env->findProxy("numpy"); + POTHOS_TEST_EQUAL(numpy.call("int8", 100).convert(), 100); POTHOS_TEST_EQUAL(numpy.call("int16", 123).convert(), 123); POTHOS_TEST_EQUAL(numpy.call("int32", 123).convert(), 123); + POTHOS_TEST_EQUAL(numpy.call("int64", 123456789).convert(), 123456789); + POTHOS_TEST_EQUAL(numpy.call("int64", 123456789).convert(), 123456789); + POTHOS_TEST_EQUAL(numpy.call("uint8", 100).convert(), 100); + POTHOS_TEST_EQUAL(numpy.call("uint16", 123).convert(), 123); + POTHOS_TEST_EQUAL(numpy.call("uint32", 123).convert(), 123); + POTHOS_TEST_EQUAL(numpy.call("uint64", 123456789).convert(), 123456789); + POTHOS_TEST_EQUAL(numpy.call("uint64", 123456789).convert(), 123456789); POTHOS_TEST_EQUAL(numpy.call("float32", 42.0f).convert(), 42.0f); POTHOS_TEST_EQUAL(numpy.call("float64", 42.0).convert(), 42.0); POTHOS_TEST_EQUAL(numpy.call("complex64", std::complex(1.0f, -2.0f)).convert>(), std::complex(1.0f, -2.0f));