diff --git a/modules/python_engine/help/en_US/xml/python_types.xml b/modules/python_engine/help/en_US/xml/python_types.xml
index 4dbcfeb523..015cfcf15c 100644
--- a/modules/python_engine/help/en_US/xml/python_types.xml
+++ b/modules/python_engine/help/en_US/xml/python_types.xml
@@ -55,6 +55,10 @@
py.bytes | double, single, int8, uint8, int16, uint16, int32, uint32, int64, uint64, logical |
+
+ py.bytearray | double, single, int8, uint8, int16, uint16, int32, uint32, int64, uint64, logical |
+
py.array.array | double, single, int8, uint8, int16, uint16, int32, uint32, int64, uint64 |
diff --git a/modules/python_engine/src/cpp/PyObjectHelpers.cpp b/modules/python_engine/src/cpp/PyObjectHelpers.cpp
index 6605926cb8..c2a941082c 100644
--- a/modules/python_engine/src/cpp/PyObjectHelpers.cpp
+++ b/modules/python_engine/src/cpp/PyObjectHelpers.cpp
@@ -12,6 +12,76 @@
//=============================================================================
namespace Nelson {
//=============================================================================
+PythonType
+getPythonType(PyObject* po)
+{
+ if (po == nullptr) {
+ return PythonType::PY_NOT_MANAGED;
+ }
+
+ PyTypeObject* pyTypeObject = Py_TYPE(po);
+
+ if (pyTypeObject == PyFloat_TypePtr) {
+ return PythonType::PY_FLOAT_TYPE;
+ }
+ if (pyTypeObject == PyBool_TypePtr) {
+ return PythonType::PY_BOOL_TYPE;
+ }
+ if (pyTypeObject == PyComplex_TypePtr) {
+ return PythonType::PY_COMPLEX_TYPE;
+ }
+ if (pyTypeObject == PyLong_TypePtr) {
+ return PythonType::PY_LONG_TYPE;
+ }
+ if (pyTypeObject == PyBytes_TypePtr) {
+ return PythonType::PY_BYTES_TYPE;
+ }
+ if (pyTypeObject == PyByteArray_TypePtr) {
+ return PythonType::PY_BYTE_ARRAY_TYPE;
+ }
+
+ std::wstring typeName = TypeName(po);
+ if (typeName == L"NoneType") {
+ return PythonType::PY_NONE_TYPE;
+ }
+ if (typeName == L"memoryview") {
+ return PythonType::PY_MEMORY_VIEW_TYPE;
+ }
+ if (typeName == L"list") {
+ return PythonType::PY_LIST_TYPE;
+ }
+ if (typeName == L"tuple") {
+ return PythonType::PY_TUPLE_TYPE;
+ }
+ if (typeName == L"dict") {
+ return PythonType::PY_DICT_TYPE;
+ }
+ if (typeName == L"str") {
+ return PythonType::PY_STR_TYPE;
+ }
+
+ std::wstring numpyPrefix = L"numpy.";
+ if (typeName.compare(0, numpyPrefix.length(), numpyPrefix) == 0) {
+ return PythonType::PY_NUMPY_TYPE;
+ }
+
+ PyObject* arrayModule = NLSPyImport_ImportModule("array");
+ if (arrayModule) {
+ PyObject* arrayType = NLSPyObject_GetAttrString(arrayModule, "array");
+ if (arrayType) {
+ if (NLSPyObject_IsInstance(po, arrayType)) {
+ NLSPy_XDECREF(arrayType);
+ NLSPy_XDECREF(arrayModule);
+ return PythonType::PY_ARRAY_ARRAY_TYPE;
+ }
+ NLSPy_XDECREF(arrayType);
+ }
+ NLSPy_XDECREF(arrayModule);
+ }
+
+ return PythonType::PY_NOT_MANAGED;
+}
+//=============================================================================
std::wstring
PyObjectToStringRepresentation(PyObject* po)
{
@@ -48,7 +118,6 @@ getPyObjectMethods(PyObject* po, bool withUnderscoreMethods)
for (Py_ssize_t i = 0; i < size; ++i) {
PyObject* item = NLSPyList_GetItem(dir_result, i);
if (item != NULL) {
-
const char* attr_name = NLSPyUnicode_AsUTF8(item);
if (attr_name) {
PyObject* method = NLSPyObject_GetAttrString(po, attr_name);
@@ -130,34 +199,17 @@ deepCopyPyObject(PyObject* obj)
const char*
getArrayArrayTypeCode(PyObject* pyObject)
{
- PyObject* arrayModule = NLSPyImport_ImportModule("array");
- if (!arrayModule) {
- return nullptr;
- }
- PyObject* arrayType = NLSPyObject_GetAttrString(arrayModule, "array");
- if (!arrayType) {
- NLSPy_XDECREF(arrayModule);
- return nullptr;
- }
- bool isInstanceArrayArray = NLSPyObject_IsInstance(pyObject, arrayType);
- if (!isInstanceArrayArray) {
- NLSPy_XDECREF(arrayType);
- NLSPy_XDECREF(arrayModule);
- return nullptr;
- }
-
PyObject* typeChar = NLSPyObject_GetAttrString(pyObject, "typecode");
if (typeChar) {
PyObject* typeStr = NLSPyUnicode_AsUTF8String(typeChar);
if (typeStr) {
const char* typeCode = NLSPyBytes_AsString(typeStr);
NLSPy_DECREF(typeStr);
+ NLSPy_XDECREF(typeChar);
return typeCode;
}
}
NLSPy_XDECREF(typeChar);
- NLSPy_XDECREF(arrayType);
- NLSPy_XDECREF(arrayModule);
return nullptr;
}
@@ -252,6 +304,12 @@ PyTypecodeToNelsonType(const char* memoryViewType)
if (strcmp(memoryViewType, "I") == 0) {
return NLS_UINT32;
}
+ if (strcmp(memoryViewType, "l") == 0) {
+ return NLS_INT32;
+ }
+ if (strcmp(memoryViewType, "L") == 0) {
+ return NLS_UINT32;
+ }
if (strcmp(memoryViewType, "h") == 0) {
return NLS_INT16;
}
@@ -264,7 +322,6 @@ PyTypecodeToNelsonType(const char* memoryViewType)
if (strcmp(memoryViewType, "B") == 0) {
return NLS_UINT8;
}
-
return NLS_UNKNOWN;
}
//=============================================================================
diff --git a/modules/python_engine/src/cpp/PyObjectHelpers.hpp b/modules/python_engine/src/cpp/PyObjectHelpers.hpp
index 04fbd456a7..01f73a2b19 100644
--- a/modules/python_engine/src/cpp/PyObjectHelpers.hpp
+++ b/modules/python_engine/src/cpp/PyObjectHelpers.hpp
@@ -15,6 +15,28 @@
//=============================================================================
namespace Nelson {
//=============================================================================
+enum PythonType
+{
+ PY_NONE_TYPE = 0,
+ PY_STR_TYPE,
+ PY_FLOAT_TYPE,
+ PY_BOOL_TYPE,
+ PY_COMPLEX_TYPE,
+ PY_LONG_TYPE,
+ PY_BYTES_TYPE,
+ PY_BYTE_ARRAY_TYPE,
+ PY_MEMORY_VIEW_TYPE,
+ PY_LIST_TYPE,
+ PY_TUPLE_TYPE,
+ PY_DICT_TYPE,
+ PY_ARRAY_ARRAY_TYPE,
+ PY_NUMPY_TYPE,
+ PY_NOT_MANAGED
+};
+//=============================================================================
+PythonType
+getPythonType(PyObject* po);
+//=============================================================================
std::wstring
PyObjectToStringRepresentation(PyObject* po);
//=============================================================================
diff --git a/modules/python_engine/src/cpp/PythonLibraryWrapper.cpp b/modules/python_engine/src/cpp/PythonLibraryWrapper.cpp
index df6c75353c..fde0561eb7 100644
--- a/modules/python_engine/src/cpp/PythonLibraryWrapper.cpp
+++ b/modules/python_engine/src/cpp/PythonLibraryWrapper.cpp
@@ -17,6 +17,8 @@ PyTypeObject* PyBool_TypePtr = nullptr;
PyTypeObject* PyComplex_TypePtr = nullptr;
PyTypeObject* PyFloat_TypePtr = nullptr;
PyTypeObject* PyLong_TypePtr = nullptr;
+PyTypeObject* PyBytes_TypePtr = nullptr;
+PyTypeObject* PyByteArray_TypePtr = nullptr;
PyTypeObject* PyMemoryView_TypePtr = nullptr;
PyTypeObject* PyUnicode_TypePtr = nullptr;
PyTypeObject* PyDict_TypePtr = nullptr;
@@ -83,7 +85,7 @@ using PROC_PyLong_FromSize_t = PyObject* (*)(size_t sz);
using PROC_PyTuple_SetItem = int (*)(PyObject* p, Py_ssize_t pos, PyObject* o);
using PROC_PyObject_GetBuffer = int (*)(PyObject* obj, Py_buffer* view, int flags);
using PROC_PyComplex_FromCComplex = PyObject* (*)(Py_complex cplx);
-using PROC_PyLong_FromLongLong = PyObject* (*)(long long);
+using PROC_PyLong_FromLongLong = PyObject* (*)(long long v);
using PROC_PyLong_FromUnsignedLongLong = PyObject* (*)(unsigned long long);
using PROC_PyBool_FromLong = PyObject* (*)(long v);
using PROC_PyLong_FromUnsignedLong = PyObject* (*)(unsigned long v);
@@ -100,6 +102,8 @@ using PROC_PyEval_GetBuiltins = PyObject* (*)(void);
using PROC_PyDict_GetItemString = PyObject* (*)(PyObject* dp, const char* key);
using PROC_PyDict_SetItemString = int (*)(PyObject* dp, const char* key, PyObject* item);
using PROC_PyDict_Keys = PyObject* (*)(PyObject* mp);
+using PROC_PyBytes_AsStringAndSize = int (*)(PyObject* obj, char** s, Py_ssize_t* len);
+using PROC_PyByteArray_AsString = char* (*)(PyObject* obj);
//=============================================================================
static std::unordered_map pythonSymbols;
//=============================================================================
@@ -127,15 +131,20 @@ loadPythonSymbols()
LOAD_PYTHON_SYMBOL(PyComplex_Type);
LOAD_PYTHON_SYMBOL(PyFloat_Type);
LOAD_PYTHON_SYMBOL(PyLong_Type);
+ LOAD_PYTHON_SYMBOL(PyBytes_Type);
+ LOAD_PYTHON_SYMBOL(PyByteArray_Type);
LOAD_PYTHON_SYMBOL(PyMemoryView_Type);
LOAD_PYTHON_SYMBOL(PyUnicode_Type);
LOAD_PYTHON_SYMBOL(PyDict_Type);
LOAD_PYTHON_SYMBOL(_Py_NoneStruct);
-
+ //=============================================================================
PyBool_TypePtr = reinterpret_cast(pythonSymbols["PyBool_Type"]);
PyComplex_TypePtr = reinterpret_cast(pythonSymbols["PyComplex_Type"]);
PyFloat_TypePtr = reinterpret_cast(pythonSymbols["PyFloat_Type"]);
PyLong_TypePtr = reinterpret_cast(pythonSymbols["PyLong_Type"]);
+ PyBytes_TypePtr = reinterpret_cast(pythonSymbols["PyBytes_Type"]);
+ PyByteArray_TypePtr = reinterpret_cast(pythonSymbols["PyByteArray_Type"]);
+
PyMemoryView_TypePtr = reinterpret_cast(pythonSymbols["PyMemoryView_Type"]);
PyUnicode_TypePtr = reinterpret_cast(pythonSymbols["PyUnicode_Type"]);
PyDict_TypePtr = reinterpret_cast(pythonSymbols["PyDict_Type"]);
@@ -191,10 +200,10 @@ loadPythonSymbols()
LOAD_PYTHON_SYMBOL(PyObject_GetBuffer);
LOAD_PYTHON_SYMBOL(PyComplex_FromCComplex);
LOAD_PYTHON_SYMBOL(PyLong_FromLongLong);
+ LOAD_PYTHON_SYMBOL(PyLong_FromLong);
LOAD_PYTHON_SYMBOL(PyLong_FromUnsignedLongLong);
LOAD_PYTHON_SYMBOL(PyBool_FromLong);
LOAD_PYTHON_SYMBOL(PyLong_FromUnsignedLong);
- LOAD_PYTHON_SYMBOL(PyLong_FromLong);
LOAD_PYTHON_SYMBOL(PyObject_VectorcallMethod);
LOAD_PYTHON_SYMBOL(PyLong_AsLongLong);
LOAD_PYTHON_SYMBOL(PyLong_AsUnsignedLongLong);
@@ -206,6 +215,8 @@ loadPythonSymbols()
LOAD_PYTHON_SYMBOL(PyDict_GetItemString);
LOAD_PYTHON_SYMBOL(PyDict_SetItemString);
LOAD_PYTHON_SYMBOL(PyDict_Keys);
+ LOAD_PYTHON_SYMBOL(PyBytes_AsStringAndSize);
+ LOAD_PYTHON_SYMBOL(PyByteArray_AsString);
return true;
}
@@ -236,6 +247,8 @@ unloadPythonLibrary()
PyComplex_TypePtr = nullptr;
PyFloat_TypePtr = nullptr;
PyLong_TypePtr = nullptr;
+ PyBytes_TypePtr = nullptr;
+ PyByteArray_TypePtr = nullptr;
PyMemoryView_TypePtr = nullptr;
PyUnicode_TypePtr = nullptr;
_Py_NoneStructPtr = nullptr;
@@ -604,7 +617,7 @@ NLSPyLong_FromUnsignedLong(unsigned long v)
PyObject*
NLSPyLong_FromLong(long v)
{
- return reinterpret_cast(pythonSymbols["PyPyLong_FromLong"])(v);
+ return reinterpret_cast(pythonSymbols["PyLong_FromLong"])(v);
}
//=============================================================================
PyObject*
@@ -688,3 +701,16 @@ NLSPyDict_Keys(PyObject* mp)
return reinterpret_cast(pythonSymbols["PyDict_Keys"])(mp);
}
//=============================================================================
+int
+NLSPyBytes_AsStringAndSize(PyObject* obj, char** s, Py_ssize_t* len)
+{
+ return reinterpret_cast(pythonSymbols["PyBytes_AsStringAndSize"])(
+ obj, s, len);
+}
+//=============================================================================
+char*
+NLSPyByteArray_AsString(PyObject* obj)
+{
+ return reinterpret_cast(pythonSymbols["PyByteArray_AsString"])(obj);
+}
+//=============================================================================
diff --git a/modules/python_engine/src/cpp/PythonLibraryWrapper.hpp b/modules/python_engine/src/cpp/PythonLibraryWrapper.hpp
index 667caf14a0..03f07b2edd 100644
--- a/modules/python_engine/src/cpp/PythonLibraryWrapper.hpp
+++ b/modules/python_engine/src/cpp/PythonLibraryWrapper.hpp
@@ -17,6 +17,8 @@ extern PyTypeObject* PyBool_TypePtr;
extern PyTypeObject* PyComplex_TypePtr;
extern PyTypeObject* PyFloat_TypePtr;
extern PyTypeObject* PyLong_TypePtr;
+extern PyTypeObject* PyBytes_TypePtr;
+extern PyTypeObject* PyByteArray_TypePtr;
extern PyTypeObject* PyMemoryView_TypePtr;
extern PyTypeObject* PyUnicode_TypePtr;
extern PyTypeObject* PyDict_TypePtr;
@@ -27,6 +29,8 @@ extern PyObject* _Py_NoneStructPtr;
#define PyComplex_Type *PyComplex_TypePtr
#define PyFloat_Type *PyFloat_TypePtr
#define PyLong_Type *PyLong_TypePtr
+#define PyBytes_Type *PyBytes_TypePtr
+#define PyByteArray_Type *PyByteArray_TypePtr
#define PyMemoryView_Type *PyMemoryView_TypePtr
#define PyUnicode_Type *PyUnicode_TypePtr
#define PyDict_Type *PyDict_TypePtr
@@ -251,3 +255,9 @@ NLSPyDict_SetItemString(PyObject* dp, const char* key, PyObject* item);
PyObject*
NLSPyDict_Keys(PyObject* mp);
//=============================================================================
+int
+NLSPyBytes_AsStringAndSize(PyObject* obj, char** s, Py_ssize_t* len);
+//=============================================================================
+char*
+NLSPyByteArray_AsString(PyObject* obj);
+//=============================================================================
diff --git a/modules/python_engine/src/cpp/PythonObjectHandle.cpp b/modules/python_engine/src/cpp/PythonObjectHandle.cpp
index a79713f2d2..edffa88c42 100644
--- a/modules/python_engine/src/cpp/PythonObjectHandle.cpp
+++ b/modules/python_engine/src/cpp/PythonObjectHandle.cpp
@@ -78,19 +78,37 @@ PythonObjectHandle::display(Interface* io)
std::wstring pyObjTypeName = getTypeName();
std::wstring strFormat;
- if ((pyObjTypeName == L"dict") || (pyObjTypeName == L"str") || (pyObjTypeName == L"NoneType")) {
+ PyObject* pyObject = (PyObject*)this->getPointer();
+ switch (getPythonType(pyObject)) {
+ case PY_DICT_TYPE:
+ case PY_STR_TYPE:
+ case PY_NONE_TYPE: {
strFormat = _W(" Python %s with no properties.");
- } else if ((pyObjTypeName == L"list") || (pyObjTypeName == L"int")) {
+ } break;
+ case PY_LIST_TYPE:
+ case PY_LONG_TYPE: {
strFormat = _W(" Python %s with values:");
- } else {
+ } break;
+ case PY_FLOAT_TYPE:
+ case PY_BOOL_TYPE:
+ case PY_COMPLEX_TYPE:
+ case PY_BYTES_TYPE:
+ case PY_BYTE_ARRAY_TYPE:
+ case PY_MEMORY_VIEW_TYPE:
+ case PY_TUPLE_TYPE:
+ case PY_ARRAY_ARRAY_TYPE:
+ case PY_NUMPY_TYPE:
+ case PY_NOT_MANAGED:
+ default: {
strFormat = _W(" Python %s:");
+ } break;
}
std::wstring msg = fmt::sprintf(strFormat, pyObjTypeName);
msg.append(L"\n");
msg.append(L"\n");
io->outputMessage(msg);
- std::wstring rep = PyObjectToStringRepresentation(((PyObject*)this->getPointer()));
+ std::wstring rep = PyObjectToStringRepresentation(pyObject);
io->outputMessage(std::wstring(L" ") + rep + L"\n");
}
//=============================================================================
@@ -123,127 +141,178 @@ PythonObjectHandle::isMethod(const std::wstring& methodName)
if (pyObject) {
PyObject* method = NLSPyObject_GetAttrString(pyObject, wstring_to_utf8(methodName).c_str());
bool callable = method && NLSPyCallable_Check(method);
- NLSPy_DECREF(method);
+ if (method) {
+ NLSPy_DECREF(method);
+ }
return callable;
}
return false;
}
//=============================================================================
-
wstringVector
PythonObjectHandle::getCastMethods()
{
- wstringVector methodsList;
+ if (!methodCastNames.empty()) {
+ return methodCastNames;
+ }
+
+ methodCastNames.push_back(L"char");
/*
- methodsList.push_back(L"char");
- methodsList.push_back(L"string");
- methodsList.push_back(L"cell");
- methodsList.push_back(L"struct");
- methodsList.push_back(L"double");
- methodsList.push_back(L"single");
- methodsList.push_back(L"logical");
- methodsList.push_back(L"int8");
- methodsList.push_back(L"uint8");
- methodsList.push_back(L"int16");
- methodsList.push_back(L"uint16");
- methodsList.push_back(L"int32");
- methodsList.push_back(L"uint32");
- methodsList.push_back(L"int64");
- methodsList.push_back(L"uint64");
+ methodsCastNames.push_back(L"char");
+ methodsCastNames.push_back(L"string");
+ methodsCastNames.push_back(L"cell");
+ methodsCastNames.push_back(L"struct");
+ methodsCastNames.push_back(L"double");
+ methodsCastNames.push_back(L"single");
+ methodsCastNames.push_back(L"logical");
+ methodsCastNames.push_back(L"int8");
+ methodsCastNames.push_back(L"uint8");
+ methodsCastNames.push_back(L"int16");
+ methodsCastNames.push_back(L"uint16");
+ methodsCastNames.push_back(L"int32");
+ methodsCastNames.push_back(L"uint32");
+ methodsCastNames.push_back(L"int64");
+ methodsCastNames.push_back(L"uint64");
*/
- if (getTypeName() == L"NoneType") {
- methodsList.push_back(L"char");
- }
- if (getTypeName() == L"str") {
- methodsList.push_back(L"numeric");
- methodsList.push_back(L"char");
- methodsList.push_back(L"string");
- methodsList.push_back(L"cell");
- }
-
- if (getTypeName() == L"memoryview") {
- methodsList.push_back(L"char");
- methodsList.push_back(L"double");
- }
-
- if (getTypeName() == L"array.array") {
- methodsList.push_back(L"numeric");
- methodsList.push_back(L"char");
- methodsList.push_back(L"string");
- methodsList.push_back(L"cell");
- methodsList.push_back(L"double");
- methodsList.push_back(L"single");
- methodsList.push_back(L"logical");
- methodsList.push_back(L"int8");
- methodsList.push_back(L"uint8");
- methodsList.push_back(L"int16");
- methodsList.push_back(L"uint16");
- methodsList.push_back(L"int32");
- methodsList.push_back(L"uint32");
- methodsList.push_back(L"int64");
- methodsList.push_back(L"uint64");
- }
- if (getTypeName() == L"dict") {
- methodsList.push_back(L"char");
- methodsList.push_back(L"struct");
- }
- if (getTypeName() == L"list") {
- methodsList.push_back(L"char");
- methodsList.push_back(L"string");
- methodsList.push_back(L"cell");
- methodsList.push_back(L"double");
- methodsList.push_back(L"single");
- methodsList.push_back(L"logical");
- methodsList.push_back(L"int8");
- methodsList.push_back(L"uint8");
- methodsList.push_back(L"int16");
- methodsList.push_back(L"uint16");
- methodsList.push_back(L"int32");
- methodsList.push_back(L"uint32");
- methodsList.push_back(L"int64");
- methodsList.push_back(L"uint64");
- }
- if (getTypeName() == L"int") {
- methodsList.push_back(L"char");
- methodsList.push_back(L"double");
- methodsList.push_back(L"single");
- methodsList.push_back(L"logical");
- methodsList.push_back(L"int8");
- methodsList.push_back(L"uint8");
- methodsList.push_back(L"int16");
- methodsList.push_back(L"uint16");
- methodsList.push_back(L"int32");
- methodsList.push_back(L"uint32");
- methodsList.push_back(L"int64");
- methodsList.push_back(L"uint64");
- }
- if (getTypeName() == L"tuple") {
- methodsList.push_back(L"char");
- methodsList.push_back(L"string");
- methodsList.push_back(L"cell");
- methodsList.push_back(L"double");
- methodsList.push_back(L"single");
- methodsList.push_back(L"logical");
- methodsList.push_back(L"int8");
- methodsList.push_back(L"uint8");
- methodsList.push_back(L"int16");
- methodsList.push_back(L"uint16");
- methodsList.push_back(L"int32");
- methodsList.push_back(L"uint32");
- methodsList.push_back(L"int64");
- methodsList.push_back(L"uint64");
- }
- return methodsList;
+ PyObject* pyObject = (PyObject*)this->getPointer();
+
+ switch (getPythonType(pyObject)) {
+ case PY_STR_TYPE: {
+ methodCastNames.push_back(L"string");
+ return methodCastNames;
+
+ } break;
+ case PY_BYTES_TYPE: {
+ methodCastNames.push_back(L"double");
+ methodCastNames.push_back(L"single");
+ methodCastNames.push_back(L"logical");
+ methodCastNames.push_back(L"int8");
+ methodCastNames.push_back(L"uint8");
+ methodCastNames.push_back(L"int16");
+ methodCastNames.push_back(L"uint16");
+ methodCastNames.push_back(L"int32");
+ methodCastNames.push_back(L"uint32");
+ methodCastNames.push_back(L"int64");
+ methodCastNames.push_back(L"uint64");
+ return methodCastNames;
+
+ } break;
+
+ case PY_MEMORY_VIEW_TYPE: {
+ methodCastNames.push_back(L"double");
+ methodCastNames.push_back(L"cell");
+ methodCastNames.push_back(L"single");
+ methodCastNames.push_back(L"logical");
+ methodCastNames.push_back(L"int8");
+ methodCastNames.push_back(L"uint8");
+ methodCastNames.push_back(L"int16");
+ methodCastNames.push_back(L"uint16");
+ methodCastNames.push_back(L"int32");
+ methodCastNames.push_back(L"uint32");
+ methodCastNames.push_back(L"int64");
+ methodCastNames.push_back(L"uint64");
+ return methodCastNames;
+
+ } break;
+ case PY_LIST_TYPE: {
+ methodCastNames.push_back(L"string");
+ methodCastNames.push_back(L"cell");
+ methodCastNames.push_back(L"double");
+ methodCastNames.push_back(L"single");
+ methodCastNames.push_back(L"logical");
+ methodCastNames.push_back(L"int8");
+ methodCastNames.push_back(L"uint8");
+ methodCastNames.push_back(L"int16");
+ methodCastNames.push_back(L"uint16");
+ methodCastNames.push_back(L"int32");
+ methodCastNames.push_back(L"uint32");
+ methodCastNames.push_back(L"int64");
+ methodCastNames.push_back(L"uint64");
+ return methodCastNames;
+ } break;
+ case PY_TUPLE_TYPE: {
+ methodCastNames.push_back(L"string");
+ methodCastNames.push_back(L"cell");
+ methodCastNames.push_back(L"double");
+ methodCastNames.push_back(L"single");
+ methodCastNames.push_back(L"logical");
+ methodCastNames.push_back(L"int8");
+ methodCastNames.push_back(L"uint8");
+ methodCastNames.push_back(L"int16");
+ methodCastNames.push_back(L"uint16");
+ methodCastNames.push_back(L"int32");
+ methodCastNames.push_back(L"uint32");
+ methodCastNames.push_back(L"int64");
+ methodCastNames.push_back(L"uint64");
+ return methodCastNames;
+
+ } break;
+ case PY_DICT_TYPE: {
+ methodCastNames.push_back(L"struct");
+ return methodCastNames;
+ } break;
+ case PY_ARRAY_ARRAY_TYPE: {
+ methodCastNames.push_back(L"numeric");
+
+ methodCastNames.push_back(L"string");
+ methodCastNames.push_back(L"cell");
+ methodCastNames.push_back(L"double");
+ methodCastNames.push_back(L"single");
+ methodCastNames.push_back(L"logical");
+ methodCastNames.push_back(L"int8");
+ methodCastNames.push_back(L"uint8");
+ methodCastNames.push_back(L"int16");
+ methodCastNames.push_back(L"uint16");
+ methodCastNames.push_back(L"int32");
+ methodCastNames.push_back(L"uint32");
+ methodCastNames.push_back(L"int64");
+ methodCastNames.push_back(L"uint64");
+ return methodCastNames;
+ } break;
+ case PY_BYTE_ARRAY_TYPE:
+ case PY_LONG_TYPE:
+ case PY_NUMPY_TYPE: {
+ methodCastNames.push_back(L"double");
+ methodCastNames.push_back(L"single");
+ methodCastNames.push_back(L"logical");
+ methodCastNames.push_back(L"int8");
+ methodCastNames.push_back(L"uint8");
+ methodCastNames.push_back(L"int16");
+ methodCastNames.push_back(L"uint16");
+ methodCastNames.push_back(L"int32");
+ methodCastNames.push_back(L"uint32");
+ methodCastNames.push_back(L"int64");
+ methodCastNames.push_back(L"uint64");
+ return methodCastNames;
+ } break;
+ case PY_NONE_TYPE:
+ case PY_FLOAT_TYPE:
+ case PY_BOOL_TYPE:
+ case PY_COMPLEX_TYPE:
+ case PY_NOT_MANAGED:
+ default: {
+ } break;
+ }
+ return methodCastNames;
}
//=============================================================================
bool
PythonObjectHandle::isCastMethod(const std::wstring& methodName)
{
- wstringVector methodsList = getCastMethods();
+ wstringVector methodCastNames = getCastMethods();
- auto it = std::find(methodsList.begin(), methodsList.end(), methodName);
- return (it != methodsList.end());
+ auto it = std::find(methodCastNames.begin(), methodCastNames.end(), methodName);
+ return (it != methodCastNames.end());
+}
+//=============================================================================
+bool
+PythonObjectHandle::isPyObjectMethod(const std::wstring& methodName)
+{
+ PyObject* pyObject = (PyObject*)this->getPointer();
+ wstringVector pythonMethodNames = getPyObjectMethods(pyObject, false);
+ auto it = std::find(pythonMethodNames.begin(), pythonMethodNames.end(), methodName);
+ return (it != pythonMethodNames.end());
}
//=============================================================================
wstringVector
@@ -252,12 +321,13 @@ PythonObjectHandle::getMethods()
if (isMainPythonInterpreter()) {
return {};
}
- wstringVector methodsList = getCastMethods();
+ wstringVector methodCastNames = getCastMethods();
PyObject* pyObject = (PyObject*)this->getPointer();
wstringVector pythonMethodNames = getPyObjectMethods(pyObject, false);
- methodsList.insert(methodsList.end(), pythonMethodNames.begin(), pythonMethodNames.end());
+ methodCastNames.insert(
+ methodCastNames.end(), pythonMethodNames.begin(), pythonMethodNames.end());
- return methodsList;
+ return methodCastNames;
}
//=============================================================================
bool
@@ -320,7 +390,26 @@ PythonObjectHandle::invokeCastCellMethod(ArrayOfVector& results)
Error(_W("Invalid Python object."));
}
- if (getTypeName() == L"tuple") {
+ switch (getPythonType(pyObject)) {
+ case PY_LIST_TYPE: {
+ Py_ssize_t sz = NLSPyList_Size(pyObject);
+
+ ArrayOf* elements = (ArrayOf*)ArrayOf::allocateArrayOf(NLS_CELL_ARRAY, sz);
+ Dimensions dims(1, sz);
+ ArrayOf res = ArrayOf(NLS_CELL_ARRAY, dims, elements);
+ for (Py_ssize_t i = 0; i < sz; ++i) {
+ PyObject* item = NLSPyList_GetItem(pyObject, i);
+ if (item != NULL) {
+ bool needDecreaseReference;
+ elements[i] = PyObjectToArrayOf(item, needDecreaseReference);
+ } else {
+ Error(_W("Cannot convert to ") + L"cell");
+ }
+ }
+ results << res;
+ return true;
+ } break;
+ case PY_TUPLE_TYPE: {
Py_ssize_t sz = NLSPyTuple_Size(pyObject);
ArrayOf* elements = (ArrayOf*)ArrayOf::allocateArrayOf(NLS_CELL_ARRAY, sz);
@@ -337,8 +426,11 @@ PythonObjectHandle::invokeCastCellMethod(ArrayOfVector& results)
}
results << res;
return true;
+ } break;
+ default: {
+ Error(_W("Cannot convert to ") + L"cell");
+ } break;
}
- Error(_W("Cannot convert to ") + L"cell");
return false;
}
//=============================================================================
@@ -350,7 +442,8 @@ PythonObjectHandle::invokeCastStructMethod(ArrayOfVector& results)
Error(_W("Invalid Python object."));
}
- if (getTypeName() == L"dict") {
+ switch (getPythonType(pyObject)) {
+ case PY_DICT_TYPE: {
PyObject* keys = NLSPyDict_Keys(pyObject);
Py_ssize_t size = NLSPyList_Size(keys);
stringVector names;
@@ -370,8 +463,11 @@ PythonObjectHandle::invokeCastStructMethod(ArrayOfVector& results)
}
results << ArrayOf::structScalarConstructor(names, values);
return true;
+ } break;
+ default: {
+ Error(_W("Cannot convert to ") + L"struct");
+ } break;
}
- Error(_W("Cannot convert to ") + L"struct");
return false;
}
//=============================================================================
@@ -382,15 +478,18 @@ PythonObjectHandle::invokeCastNumericMethod(ArrayOfVector& results)
if (!pyObject) {
Error(_W("Invalid Python object."));
}
-
- if (getTypeName() == L"memoryview") {
+ switch (getPythonType(pyObject)) {
+ case PY_MEMORY_VIEW_TYPE: {
results << PyMemoryViewToArrayOf(pyObject);
return true;
- }
- const char* typeCode = getArrayArrayTypeCode(pyObject);
- if (typeCode) {
- results << PyArrayArrayToArrayOf(pyObject);
- return true;
+ } break;
+ case PY_ARRAY_ARRAY_TYPE: {
+ const char* typeCode = getArrayArrayTypeCode(pyObject);
+ if (typeCode) {
+ results << PyArrayArrayToArrayOf(pyObject);
+ return true;
+ }
+ } break;
}
return false;
}
@@ -402,13 +501,46 @@ PythonObjectHandle::invokeCastCharMethod(ArrayOfVector& results)
if (!pyObject) {
Error(_W("Invalid Python object."));
}
- if (getTypeName() == L"str") {
+ switch (getPythonType(pyObject)) {
+ case PY_STR_TYPE: {
std::string str = std::string(NLSPyUnicode_AsUTF8(pyObject));
results << ArrayOf::characterArrayConstructor(str);
return true;
+ } break;
+ default: {
+ results << ArrayOf::characterArrayConstructor(PyObjectToStringRepresentation(pyObject));
+ return true;
+ } break;
}
+ return false;
+}
+//=============================================================================
+template
+bool
+handleListOrTupleToString(
+ PyObject* pyObject, GetSizeFunc getSizeFunc, GetItemFunc getItemFunc, ArrayOfVector& results)
+{
+ Py_ssize_t sz = getSizeFunc(pyObject);
+ ArrayOf* elements = (ArrayOf*)ArrayOf::allocateArrayOf(NLS_STRING_ARRAY, sz);
+ ArrayOf res = ArrayOf(NLS_STRING_ARRAY, Dimensions(1, sz), elements);
- results << ArrayOf::characterArrayConstructor(PyObjectToStringRepresentation(pyObject));
+ for (Py_ssize_t i = 0; i < sz; ++i) {
+ PyObject* item = getItemFunc(pyObject, i);
+ if (item != NULL) {
+ if (getPythonType(item) == PY_STR_TYPE) {
+ std::string str = std::string(NLSPyUnicode_AsUTF8(item));
+ elements[i] = ArrayOf::characterArrayConstructor(str);
+ } else {
+ elements[i]
+ = ArrayOf::characterArrayConstructor(PyObjectToStringRepresentation(item));
+ }
+ } else {
+ Error(_W("All Python elements must be convertible as scalar to the requested type."));
+ return false;
+ }
+ }
+
+ results << res;
return true;
}
//=============================================================================
@@ -418,149 +550,326 @@ PythonObjectHandle::invokeCastStringMethod(ArrayOfVector& results)
PyObject* pyObject = (PyObject*)this->getPointer();
if (!pyObject) {
Error(_W("Invalid Python object."));
+ return false;
}
- if (getTypeName() == L"str") {
+
+ switch (getPythonType(pyObject)) {
+ case PY_STR_TYPE: {
std::string str = std::string(NLSPyUnicode_AsUTF8(pyObject));
results << ArrayOf::stringArrayConstructor(str);
return true;
+ } break;
+ case PY_LIST_TYPE: {
+ auto getSizeFunc = [](PyObject* obj) { return NLSPyList_Size(obj); };
+ auto getItemFunc = [](PyObject* obj, Py_ssize_t i) { return NLSPyList_GetItem(obj, i); };
+ return handleListOrTupleToString(pyObject, getSizeFunc, getItemFunc, results);
+ } break;
+ case PY_TUPLE_TYPE: {
+ auto getSizeFunc = [](PyObject* obj) { return NLSPyTuple_Size(obj); };
+ auto getItemFunc = [](PyObject* obj, Py_ssize_t i) { return NLSPyTuple_GetItem(obj, i); };
+ return handleListOrTupleToString(pyObject, getSizeFunc, getItemFunc, results);
+ } break;
}
return false;
}
//=============================================================================
+template
bool
-PythonObjectHandle::invokeCastDoubleMethod(ArrayOfVector& results)
+castRealMethod(PyObject* pyObject, NelsonType nelsonType, ArrayOfVector& results)
{
- PyObject* pyObject = (PyObject*)this->getPointer();
if (!pyObject) {
Error(_W("Invalid Python object."));
}
- if (getTypeName() == L"memoryview") {
+
+ PythonType pyType = getPythonType(pyObject);
+ switch (pyType) {
+ case PY_NUMPY_TYPE: {
+ PyObject* numpy = NLSPyImport_ImportModule("numpy.core._multiarray_umath");
+ // bool isarray = PyArray_Check(pyObject);
+ // PyArrayObject* pyArray = (PyArrayObject*)pyObject;
+
+ ////// Get array dimensions and data pointer
+ // npy_intp* dims = PyArray_DIMS(pyArray);
+ // T* dataPtr = (T*)PyArray_DATA(pyArray);
+ // ArrayOf res(nelsonType, Dimensions(1, 4), dataPtr);
+ // results << res;
+ // return true;
+
+ //// Create ArrayOf object with appropriate dimensions and data
+ // indexType r = dims[0];
+ // indexType c = dims[0] + PyArray_NDIM(pyArray);
+ // Dimensions arrayDims(r, c);
+ // ArrayOf res(nelsonType, arrayDims, dataPtr);
+ // results << res;
+ // return true;
+ } break;
+ case PY_FLOAT_TYPE: {
+ double result = NLSPyFloat_AsDouble(pyObject);
+ ArrayOf res = ArrayOf::doubleConstructor(result);
+ res.promoteType(nelsonType);
+ results << res;
+ return true;
+ } break;
+ case PY_BOOL_TYPE: {
+ logical value = (logical)NLSPyObject_IsTrue(pyObject);
+ ArrayOf res = ArrayOf::logicalConstructor(value);
+ res.promoteType(nelsonType);
+ results << res;
+ return true;
+ } break;
+ case PY_COMPLEX_TYPE: {
+ std::complex value;
+ Py_complex pyCplx = NLSPyComplex_AsCComplex(pyObject);
+ ArrayOf res = ArrayOf::dcomplexConstructor(pyCplx.real, pyCplx.imag);
+ if (nelsonType == NLS_DOUBLE) {
+ res.promoteType(NLS_DCOMPLEX);
+ } else {
+ res.promoteType(NLS_SCOMPLEX);
+ }
+ results << res;
+ return true;
+ } break;
+ case PY_LONG_TYPE: {
+ double value = NLSPyLong_AsDouble(pyObject);
+ ArrayOf res = ArrayOf::doubleConstructor(value);
+ res.promoteType(nelsonType);
+ results << res;
+ return true;
+ } break;
+ case PY_BYTES_TYPE: {
+ char* buffer;
+ Py_ssize_t size;
+ if (NLSPyBytes_AsStringAndSize(pyObject, &buffer, &size) == 0) {
+ T* ptr = (T*)ArrayOf::allocateArrayOf(nelsonType, size);
+ ArrayOf res(nelsonType, Dimensions(1, size), ptr);
+ for (size_t k = 0; k < (size_t)size; ++k) {
+ ptr[k] = (T)buffer[k];
+ }
+ results << res;
+ return true;
+ }
+ } break;
+ case PY_BYTE_ARRAY_TYPE: {
+ char* buffer = NLSPyByteArray_AsString(pyObject);
+ size_t len = strlen(buffer);
+ T* ptr = (T*)ArrayOf::allocateArrayOf(nelsonType, len);
+ ArrayOf res(nelsonType, Dimensions(1, len), ptr);
+ for (size_t k = 0; k < len; ++k) {
+ ptr[k] = (T)buffer[k];
+ }
+ results << res;
+ return true;
+ } break;
+ case PY_MEMORY_VIEW_TYPE: {
ArrayOf res = PyMemoryViewToArrayOf(pyObject);
if (res.isComplex()) {
- res.promoteType(NLS_DCOMPLEX);
+ if (nelsonType == NLS_DOUBLE) {
+ res.promoteType(NLS_DCOMPLEX);
+ } else {
+ res.promoteType(NLS_SCOMPLEX);
+ }
} else {
- res.promoteType(NLS_DOUBLE);
+ res.promoteType(nelsonType);
}
results << res;
return true;
- }
- if (getTypeName() == L"tuple") {
- Py_ssize_t sz = NLSPyTuple_Size(pyObject);
- double* elements = (double*)ArrayOf::allocateArrayOf(NLS_DCOMPLEX, sz);
+ } break;
+ case PY_LIST_TYPE:
+ case PY_TUPLE_TYPE: {
+ Py_ssize_t sz
+ = (pyType == PY_LIST_TYPE) ? NLSPyList_Size(pyObject) : NLSPyTuple_Size(pyObject);
+ T* elements = (T*)ArrayOf::allocateArrayOf(
+ nelsonType == NLS_DOUBLE ? NLS_DCOMPLEX : NLS_SCOMPLEX, sz);
Dimensions dims(1, sz);
- ArrayOf res = ArrayOf(NLS_DCOMPLEX, dims, elements);
+ ArrayOf res
+ = ArrayOf(nelsonType == NLS_DOUBLE ? NLS_DCOMPLEX : NLS_SCOMPLEX, dims, elements);
indexType k = 0;
bool allReal = true;
for (Py_ssize_t i = 0; i < sz; ++i) {
- PyObject* item = NLSPyTuple_GetItem(pyObject, i);
+ PyObject* item = (pyType == PY_LIST_TYPE) ? NLSPyList_GetItem(pyObject, i)
+ : NLSPyTuple_GetItem(pyObject, i);
if (item != NULL) {
bool needDecreaseReference;
- ArrayOf r = PyObjectToArrayOf(item, needDecreaseReference);
- if (r.isNumeric()) {
- if (r.isComplex()) {
- std::complex c = r.getContentAsDoubleComplexScalar();
- elements[k] = c.real();
- elements[k + 1] = c.imag();
- allReal = false;
+ ArrayOfVector rr;
+ if (castRealMethod(item, NLS_DOUBLE, rr)) {
+ ArrayOf r = rr[0];
+ if (r.isNumeric()) {
+ if (r.isComplex()) {
+ std::complex c = r.getContentAsDoubleComplexScalar();
+ elements[k] = (T)c.real();
+ elements[k + 1] = (T)c.imag();
+ allReal = false;
+ } else {
+ elements[k] = (T)r.getContentAsDoubleScalar();
+ elements[k + 1] = 0;
+ }
+ k = k + 2;
} else {
- elements[k] = r.getContentAsDoubleScalar();
- elements[k + 1] = 0;
+ Error(_W("All Python elements must be convertible as scalar to the "
+ "requested "
+ "type."));
+ return false;
}
- k = k + 2;
} else {
+ Error(_W("All Python elements must be convertible as scalar to the requested "
+ "type."));
return false;
}
} else {
+ Error(_W("All Python elements must be convertible as scalar to the requested "
+ "type."));
return false;
}
}
if (allReal) {
- res.promoteType(NLS_DOUBLE);
+ res.promoteType(nelsonType);
}
results << res;
return true;
- }
-
- const char* typeCode = getArrayArrayTypeCode(pyObject);
- if (typeCode) {
- ArrayOf res = PyArrayArrayToArrayOf(pyObject);
- if (res.isComplex()) {
- res.promoteType(NLS_DCOMPLEX);
- } else {
- res.promoteType(NLS_DOUBLE);
+ } break;
+ case PY_ARRAY_ARRAY_TYPE: {
+ const char* typeCode = getArrayArrayTypeCode(pyObject);
+ if (typeCode) {
+ ArrayOf res = PyArrayArrayToArrayOf(pyObject);
+ if (res.isComplex()) {
+ if (nelsonType == NLS_DOUBLE) {
+ res.promoteType(NLS_DCOMPLEX);
+ } else {
+ res.promoteType(NLS_SCOMPLEX);
+ }
+ } else {
+ res.promoteType(nelsonType);
+ }
+ results << res;
+ return true;
}
- results << res;
- return true;
+ } break;
}
return false;
}
//=============================================================================
bool
+PythonObjectHandle::invokeCastDoubleMethod(ArrayOfVector& results)
+{
+ PyObject* pyObject = (PyObject*)this->getPointer();
+ return castRealMethod(pyObject, NLS_DOUBLE, results);
+}
+//=============================================================================
+bool
PythonObjectHandle::invokeCastSingleMethod(ArrayOfVector& results)
{
PyObject* pyObject = (PyObject*)this->getPointer();
+ return castRealMethod(pyObject, NLS_SINGLE, results);
+}
+//=============================================================================
+template
+bool
+castIntegerMethod(PyObject* pyObject, NelsonType nelsonType, ArrayOfVector& results)
+{
if (!pyObject) {
Error(_W("Invalid Python object."));
}
-
- const char* typeCode = getArrayArrayTypeCode(pyObject);
- if (typeCode) {
- ArrayOf res = PyArrayArrayToArrayOf(pyObject);
- if (res.isComplex()) {
- res.promoteType(NLS_SCOMPLEX);
- } else {
- res.promoteType(NLS_SINGLE);
- }
+ PythonType pyType = getPythonType(pyObject);
+ switch (pyType) {
+ case PY_FLOAT_TYPE: {
+ double result = NLSPyFloat_AsDouble(pyObject);
+ ArrayOf res = ArrayOf::doubleConstructor(result);
+ res.promoteType(nelsonType);
results << res;
return true;
- }
- if (getTypeName() == L"memoryview") {
- ArrayOf res = PyMemoryViewToArrayOf(pyObject);
- if (res.isComplex()) {
- res.promoteType(NLS_DCOMPLEX);
- } else {
- res.promoteType(NLS_DOUBLE);
+ } break;
+ case PY_BOOL_TYPE: {
+ logical value = (logical)NLSPyObject_IsTrue(pyObject);
+ ArrayOf res = ArrayOf::logicalConstructor(value);
+ res.promoteType(nelsonType);
+ results << res;
+ return true;
+ } break;
+ case PY_COMPLEX_TYPE: {
+ std::complex value;
+ Py_complex pyCplx = NLSPyComplex_AsCComplex(pyObject);
+ ArrayOf res = ArrayOf::dcomplexConstructor(pyCplx.real, pyCplx.imag);
+ res.promoteType(nelsonType);
+ results << res;
+ return true;
+ } break;
+ case PY_LONG_TYPE: {
+ double value = NLSPyLong_AsDouble(pyObject);
+ ArrayOf res = ArrayOf::doubleConstructor(value);
+ res.promoteType(nelsonType);
+ results << res;
+ return true;
+ } break;
+ case PY_BYTES_TYPE: {
+ char* buffer;
+ Py_ssize_t size;
+ if (NLSPyBytes_AsStringAndSize(pyObject, &buffer, &size) == 0) {
+ T* ptr = (T*)ArrayOf::allocateArrayOf(nelsonType, size);
+ ArrayOf res(nelsonType, Dimensions(1, size), ptr);
+ for (size_t k = 0; k < (size_t)size; ++k) {
+ ptr[k] = (T)buffer[k];
+ }
+ results << res;
+ return true;
+ }
+ } break;
+ case PY_BYTE_ARRAY_TYPE: {
+ char* buffer = NLSPyByteArray_AsString(pyObject);
+ size_t len = strlen(buffer);
+ T* ptr = (T*)ArrayOf::allocateArrayOf(nelsonType, len);
+ ArrayOf res(nelsonType, Dimensions(1, len), ptr);
+ for (size_t k = 0; k < len; ++k) {
+ ptr[k] = (T)buffer[k];
}
results << res;
return true;
- }
- if (getTypeName() == L"tuple") {
- Py_ssize_t sz = NLSPyTuple_Size(pyObject);
- double* elements = (double*)ArrayOf::allocateArrayOf(NLS_SCOMPLEX, sz);
- Dimensions dims(1, sz);
- ArrayOf res = ArrayOf(NLS_SCOMPLEX, dims, elements);
- indexType k = 0;
- bool allReal = true;
+ } break;
+ case PY_ARRAY_ARRAY_TYPE: {
+ const char* typeCode = getArrayArrayTypeCode(pyObject);
+ if (typeCode) {
+ ArrayOf res = PyArrayArrayToArrayOf(pyObject);
+ res.promoteType(nelsonType);
+ results << res;
+ return true;
+ }
+ } break;
+ case PY_LIST_TYPE:
+ case PY_TUPLE_TYPE: {
+ Py_ssize_t sz
+ = (pyType == PY_LIST_TYPE) ? NLSPyList_Size(pyObject) : NLSPyTuple_Size(pyObject);
+ T* values = (T*)ArrayOf::allocateArrayOf(nelsonType, sz);
+ ArrayOf res = ArrayOf(nelsonType, Dimensions(1, sz), values);
for (Py_ssize_t i = 0; i < sz; ++i) {
- PyObject* item = NLSPyTuple_GetItem(pyObject, i);
+ PyObject* item = (pyType == PY_LIST_TYPE) ? NLSPyList_GetItem(pyObject, i)
+ : NLSPyTuple_GetItem(pyObject, i);
if (item != NULL) {
- bool needDecreaseReference;
- ArrayOf r = PyObjectToArrayOf(item, needDecreaseReference);
- if (r.isNumeric()) {
- if (r.isComplex()) {
- std::complex c = r.getContentAsSingleComplexScalar();
- elements[k] = c.real();
- elements[k + 1] = c.imag();
- allReal = false;
- } else {
- elements[k] = r.getContentAsSingleScalar();
- elements[k + 1] = 0;
- }
- k = k + 2;
+ ArrayOfVector rr;
+ if (castIntegerMethod(item, nelsonType, rr)) {
+ T* ptr = (T*)rr[0].getDataPointer();
+ values[i] = ptr[0];
} else {
+ Error(_W("All Python elements must be convertible as scalar to the "
+ "requested "
+ "type."));
return false;
}
} else {
+ Error(_W("All Python elements must be convertible as scalar to the "
+ "requested "
+ "type."));
return false;
}
}
- if (allReal) {
- res.promoteType(NLS_SINGLE);
- }
results << res;
return true;
+ } break;
+ case PY_MEMORY_VIEW_TYPE: {
+ ArrayOf res = PyMemoryViewToArrayOf(pyObject);
+ res.promoteType(nelsonType);
+ results << res;
+ return true;
+ } break;
}
-
return false;
}
//=============================================================================
@@ -568,210 +877,65 @@ bool
PythonObjectHandle::invokeCastLogicalMethod(ArrayOfVector& results)
{
PyObject* pyObject = (PyObject*)this->getPointer();
- if (!pyObject) {
- Error(_W("Invalid Python object."));
- }
- const char* typeCode = getArrayArrayTypeCode(pyObject);
- if (typeCode) {
- ArrayOf res = PyArrayArrayToArrayOf(pyObject);
- res.promoteType(NLS_LOGICAL);
- results << res;
- return true;
- }
- if (getTypeName() == L"memoryview") {
- ArrayOf res = PyMemoryViewToArrayOf(pyObject);
- res.promoteType(NLS_LOGICAL);
- results << res;
- return true;
- }
- return false;
+ return castIntegerMethod(pyObject, NLS_LOGICAL, results);
}
//=============================================================================
bool
PythonObjectHandle::invokeCastInt8Method(ArrayOfVector& results)
{
PyObject* pyObject = (PyObject*)this->getPointer();
- if (!pyObject) {
- Error(_W("Invalid Python object."));
- }
- const char* typeCode = getArrayArrayTypeCode(pyObject);
- if (typeCode) {
- ArrayOf res = PyArrayArrayToArrayOf(pyObject);
- res.promoteType(NLS_INT8);
- results << res;
- return true;
- }
- if (getTypeName() == L"memoryview") {
- ArrayOf res = PyMemoryViewToArrayOf(pyObject);
- res.promoteType(NLS_INT8);
- results << res;
- return true;
- }
- return false;
+ return castIntegerMethod(pyObject, NLS_INT8, results);
}
//=============================================================================
bool
PythonObjectHandle::invokeCastInt16Method(ArrayOfVector& results)
{
PyObject* pyObject = (PyObject*)this->getPointer();
- if (!pyObject) {
- Error(_W("Invalid Python object."));
- }
- const char* typeCode = getArrayArrayTypeCode(pyObject);
- if (typeCode) {
- ArrayOf res = PyArrayArrayToArrayOf(pyObject);
- res.promoteType(NLS_INT16);
- results << res;
- return true;
- }
- if (getTypeName() == L"memoryview") {
- ArrayOf res = PyMemoryViewToArrayOf(pyObject);
- res.promoteType(NLS_INT16);
- results << res;
- return true;
- }
- return false;
+ return castIntegerMethod(pyObject, NLS_INT16, results);
}
//=============================================================================
bool
PythonObjectHandle::invokeCastInt32Method(ArrayOfVector& results)
{
PyObject* pyObject = (PyObject*)this->getPointer();
- if (!pyObject) {
- Error(_W("Invalid Python object."));
- }
- const char* typeCode = getArrayArrayTypeCode(pyObject);
- if (typeCode) {
- ArrayOf res = PyArrayArrayToArrayOf(pyObject);
- res.promoteType(NLS_INT32);
- results << res;
- return true;
- }
- if (getTypeName() == L"memoryview") {
- ArrayOf res = PyMemoryViewToArrayOf(pyObject);
- res.promoteType(NLS_INT32);
- results << res;
- return true;
- }
- return false;
+ return castIntegerMethod(pyObject, NLS_INT32, results);
}
//=============================================================================
bool
PythonObjectHandle::invokeCastInt64Method(ArrayOfVector& results)
{
PyObject* pyObject = (PyObject*)this->getPointer();
- if (!pyObject) {
- Error(_W("Invalid Python object."));
- }
- const char* typeCode = getArrayArrayTypeCode(pyObject);
- if (typeCode) {
- ArrayOf res = PyArrayArrayToArrayOf(pyObject);
- res.promoteType(NLS_INT64);
- results << res;
- return true;
- }
- if (getTypeName() == L"memoryview") {
- ArrayOf res = PyMemoryViewToArrayOf(pyObject);
- res.promoteType(NLS_INT64);
- results << res;
- return true;
- }
- return false;
+ return castIntegerMethod(pyObject, NLS_INT64, results);
}
//=============================================================================
bool
PythonObjectHandle::invokeCastUInt8Method(ArrayOfVector& results)
{
PyObject* pyObject = (PyObject*)this->getPointer();
- if (!pyObject) {
- Error(_W("Invalid Python object."));
- }
- const char* typeCode = getArrayArrayTypeCode(pyObject);
- if (typeCode) {
- ArrayOf res = PyArrayArrayToArrayOf(pyObject);
- res.promoteType(NLS_UINT8);
- results << res;
- return true;
- }
- if (getTypeName() == L"memoryview") {
- ArrayOf res = PyMemoryViewToArrayOf(pyObject);
- res.promoteType(NLS_UINT8);
- results << res;
- return true;
- }
- return false;
+ return castIntegerMethod(pyObject, NLS_UINT8, results);
}
//=============================================================================
bool
PythonObjectHandle::invokeCastUInt16Method(ArrayOfVector& results)
{
PyObject* pyObject = (PyObject*)this->getPointer();
- if (!pyObject) {
- Error(_W("Invalid Python object."));
- }
- const char* typeCode = getArrayArrayTypeCode(pyObject);
- if (typeCode) {
- ArrayOf res = PyArrayArrayToArrayOf(pyObject);
- res.promoteType(NLS_UINT16);
- results << res;
- return true;
- }
- if (getTypeName() == L"memoryview") {
- ArrayOf res = PyMemoryViewToArrayOf(pyObject);
- res.promoteType(NLS_UINT16);
- results << res;
- return true;
- }
- return false;
+ return castIntegerMethod(pyObject, NLS_UINT16, results);
}
//=============================================================================
bool
PythonObjectHandle::invokeCastUInt32Method(ArrayOfVector& results)
{
PyObject* pyObject = (PyObject*)this->getPointer();
- if (!pyObject) {
- Error(_W("Invalid Python object."));
- }
- const char* typeCode = getArrayArrayTypeCode(pyObject);
- if (typeCode) {
- ArrayOf res = PyArrayArrayToArrayOf(pyObject);
- res.promoteType(NLS_UINT32);
- results << res;
- return true;
- }
- if (getTypeName() == L"memoryview") {
- ArrayOf res = PyMemoryViewToArrayOf(pyObject);
- res.promoteType(NLS_UINT32);
- results << res;
- return true;
- }
- return false;
+ return castIntegerMethod(pyObject, NLS_UINT32, results);
}
//=============================================================================
bool
PythonObjectHandle::invokeCastUInt64Method(ArrayOfVector& results)
{
PyObject* pyObject = (PyObject*)this->getPointer();
- if (!pyObject) {
- Error(_W("Invalid Python object."));
- }
- const char* typeCode = getArrayArrayTypeCode(pyObject);
- if (typeCode) {
- ArrayOf res = PyArrayArrayToArrayOf(pyObject);
- res.promoteType(NLS_UINT64);
- results << res;
- return true;
- }
- if (getTypeName() == L"memoryview") {
- ArrayOf res = PyMemoryViewToArrayOf(pyObject);
- res.promoteType(NLS_UINT64);
- results << res;
- return true;
- }
- return false;
+ return castIntegerMethod(pyObject, NLS_UINT64, results);
}
//=============================================================================
-
bool
PythonObjectHandle::invokeCastMethod(const std::wstring& methodName, ArrayOfVector& results)
{
diff --git a/modules/python_engine/src/cpp/PythonTypesWrapper.cpp b/modules/python_engine/src/cpp/PythonTypesWrapper.cpp
index 91383bf89c..62ebc30e9d 100644
--- a/modules/python_engine/src/cpp/PythonTypesWrapper.cpp
+++ b/modules/python_engine/src/cpp/PythonTypesWrapper.cpp
@@ -142,7 +142,7 @@ convertDoubleArray(const ArrayOf& A)
}
if (A.isScalar()) {
pyObj = NLSPyFloat_FromDouble(A.getContentAsDoubleScalar());
- } else if (A.isEmpty() || A.isVector()) {
+ } else if (!A.isComplex() && (A.isEmpty() || A.isVector())) {
pyObj = rowVectorToPyArray(
A.getDataPointer(), A.getElementCount(), nelsonTypeToTypeCode(A.getDataClass()));
} else {
@@ -157,7 +157,7 @@ convertSingleArray(const ArrayOf& A)
PyObject* pyObj = nullptr;
if (A.isScalar()) {
pyObj = NLSPyFloat_FromDouble((double)A.getContentAsSingleScalar());
- } else if (A.isEmpty() || A.isVector()) {
+ } else if (!A.isComplex() && (A.isEmpty() || A.isVector())) {
pyObj = rowVectorToPyArray(
A.getDataPointer(), A.getElementCount(), nelsonTypeToTypeCode(A.getDataClass()));
} else {
@@ -179,9 +179,6 @@ convertDoubleComplexArray(const ArrayOf& A)
pyCplx.imag = cplx.imag();
pyCplx.real = cplx.real();
pyObj = NLSPyComplex_FromCComplex(pyCplx);
- } else if (A.isEmpty() || A.isVector()) {
- pyObj = rowVectorToPyArray(
- A.getDataPointer(), A.getElementCount() * 2, nelsonTypeToTypeCode(A.getDataClass()));
} else {
pyObj = arrayToMemoryView(A.getDataPointer(), A.getDataClass(), A.getDimensions());
}
@@ -198,9 +195,6 @@ convertSingleComplexArray(const ArrayOf& A)
pyCplx.imag = cplx.imag();
pyCplx.real = cplx.real();
pyObj = NLSPyComplex_FromCComplex(pyCplx);
- } else if (A.isEmpty() || A.isVector()) {
- pyObj = rowVectorToPyArray(
- A.getDataPointer(), A.getElementCount() * 2, nelsonTypeToTypeCode(A.getDataClass()));
} else {
pyObj = arrayToMemoryView(A.getDataPointer(), A.getDataClass(), A.getDimensions());
}
@@ -372,12 +366,14 @@ rowVectorToPyArray(const void* ptrValues, size_t len, const char* dataType)
for (size_t k = 0; k < len; k++) {
PyObject* item = nullptr;
if (!item && strcmp(dataType, "Zf") == 0) {
+ // not supported
Py_complex pyCplx;
pyCplx.real = ((const single*)ptrValues)[k];
pyCplx.imag = ((const single*)ptrValues)[k + 1];
item = NLSPyComplex_FromCComplex(pyCplx);
}
if (!item && strcmp(dataType, "Zd") == 0) {
+ // not supported
Py_complex pyCplx
= { ((const double*)ptrValues)[k], ((const double*)ptrValues)[k + 1] };
item = NLSPyComplex_FromCComplex(pyCplx);
@@ -397,12 +393,17 @@ rowVectorToPyArray(const void* ptrValues, size_t len, const char* dataType)
if (!item && strcmp(dataType, "I") == 0) {
item = NLSPyLong_FromUnsignedLong((unsigned long)((const uint32*)ptrValues)[k]);
}
+ if (!item && strcmp(dataType, "L") == 0) {
+ item = NLSPyLong_FromUnsignedLong((unsigned long)((const uint32*)ptrValues)[k]);
+ }
if (!item && strcmp(dataType, "Q") == 0) {
item
= NLSPyLong_FromUnsignedLongLong((unsigned long long)((const uint64*)ptrValues)[k]);
}
if (!item && strcmp(dataType, "b") == 0) {
- item = NLSPyLong_FromLong((long)((const int8*)ptrValues)[k]);
+ int8* ptr = (int8*)(ptrValues);
+ int8 i8value = ptr[k];
+ item = NLSPyLong_FromLong((long)(i8value));
}
if (!item && strcmp(dataType, "h") == 0) {
item = NLSPyLong_FromLong((long)((const int16*)ptrValues)[k]);
@@ -410,6 +411,9 @@ rowVectorToPyArray(const void* ptrValues, size_t len, const char* dataType)
if (!item && strcmp(dataType, "i") == 0) {
item = NLSPyLong_FromLong((long)((const int32*)ptrValues)[k]);
}
+ if (!item && strcmp(dataType, "l") == 0) {
+ item = NLSPyLong_FromLong((long)((const int32*)ptrValues)[k]);
+ }
if (!item && strcmp(dataType, "q") == 0) {
item = NLSPyLong_FromLongLong((long long)((const int64*)ptrValues)[k]);
}
@@ -495,7 +499,7 @@ arrayToMemoryView(const void* data, NelsonType nelsonType, const Dimensions& dim
}
pyBuffer.ndim = (int)dims.getLength();
- Py_ssize_t* shape = new Py_ssize_t[dims.getLength()];
+ Py_ssize_t* shape = (Py_ssize_t*)malloc(sizeof(Py_ssize_t) * dims.getLength());
for (size_t k = 0; k < dims.getLength(); ++k) {
shape[k] = dims.getAt(k);
}
@@ -508,15 +512,10 @@ arrayToMemoryView(const void* data, NelsonType nelsonType, const Dimensions& dim
}
Py_ssize_t sz = getTypeSize(nelsonType);
-
- if (nelsonType == NLS_SCOMPLEX || nelsonType == NLS_DCOMPLEX) {
- memcpy(ptr, data, sz * dims.getElementCount() * 2);
- } else {
- memcpy(ptr, data, sz * dims.getElementCount());
- }
+ memcpy(ptr, data, sz * dims.getElementCount());
pyBuffer.buf = ptr;
- Py_ssize_t* strides = new Py_ssize_t[dims.getLength()];
+ Py_ssize_t* strides = (Py_ssize_t*)malloc(sizeof(Py_ssize_t) * dims.getLength());
for (size_t k = 0; k < dims.getLength(); ++k) {
strides[k] = sz;
}
@@ -544,40 +543,30 @@ PyMemoryViewToArrayOf(PyObject* pyObject)
if (NLSPyObject_GetBuffer(pyObject, &pyBuffer, PyBUF_FORMAT | PyBUF_STRIDES) == -1) {
Error(_W("Failed to get buffer from memory view."));
}
+ size_t nbElements = pyBuffer.len / pyBuffer.itemsize;
+
size_t ndim = pyBuffer.ndim;
std::vector dimsVector;
dimsVector.reserve(ndim);
for (size_t k = 0; k < ndim; ++k) {
dimsVector.push_back(pyBuffer.shape[k]);
}
-
+ if (nbElements > 0 && dimsVector.empty()) {
+ dimsVector.push_back(1);
+ dimsVector.push_back(nbElements);
+ }
+ if (dimsVector.size() == 1) {
+ indexType d = dimsVector[0];
+ dimsVector[0] = 1;
+ dimsVector.push_back(d);
+ }
Dimensions dims(dimsVector);
NelsonType nelsonType = PyTypecodeToNelsonType(pyBuffer.format);
switch (nelsonType) {
- case NLS_DOUBLE: {
- double* data = (double*)pyBuffer.buf;
- double* ptr = (double*)ArrayOf::allocateArrayOf(nelsonType, dims.getElementCount());
- memcpy(ptr, data, dims.getElementCount() * sizeof(double));
- return ArrayOf(nelsonType, dims, ptr);
- } break;
- case NLS_SINGLE: {
- single* data = (single*)pyBuffer.buf;
- single* ptr = (single*)ArrayOf::allocateArrayOf(nelsonType, dims.getElementCount());
- memcpy(ptr, data, dims.getElementCount() * sizeof(single));
- return ArrayOf(nelsonType, dims, ptr);
- } break;
- case NLS_DCOMPLEX: {
- double* data = (double*)pyBuffer.buf;
- double* ptr = (double*)ArrayOf::allocateArrayOf(nelsonType, dims.getElementCount());
- memcpy(ptr, data, 2 * dims.getElementCount() * sizeof(double));
- return ArrayOf(nelsonType, dims, ptr);
- } break;
- case NLS_SCOMPLEX: {
- single* data = (single*)pyBuffer.buf;
- single* ptr = (single*)ArrayOf::allocateArrayOf(nelsonType, dims.getElementCount());
- memcpy(ptr, data, 2 * dims.getElementCount() * sizeof(single));
- return ArrayOf(nelsonType, dims, ptr);
- } break;
+ case NLS_DCOMPLEX:
+ case NLS_SCOMPLEX:
+ case NLS_DOUBLE:
+ case NLS_SINGLE:
case NLS_INT8:
case NLS_INT16:
case NLS_INT32:
@@ -587,10 +576,11 @@ PyMemoryViewToArrayOf(PyObject* pyObject)
case NLS_UINT32:
case NLS_UINT64:
case NLS_LOGICAL: {
- logical* data = (logical*)pyBuffer.buf;
- logical* ptr = (logical*)ArrayOf::allocateArrayOf(NLS_LOGICAL, dims.getElementCount());
- memcpy(ptr, data, dims.getElementCount() * sizeof(logical));
- return ArrayOf(NLS_LOGICAL, dims, ptr);
+ void* data = (void*)pyBuffer.buf;
+ void* ptr = (void*)ArrayOf::allocateArrayOf(nelsonType, dims.getElementCount());
+ ArrayOf res = ArrayOf(nelsonType, dims, ptr);
+ memcpy(ptr, data, res.getByteSize());
+ return res;
} break;
case NLS_CHAR: {
} break;
@@ -732,9 +722,8 @@ PyArrayArrayToDoubleArrayOf(NelsonType nelsonType, PyObject* pyObject, Py_ssize_
{
Dimensions dimsVector(1, vectorSize);
void* ptr = ArrayOf::allocateArrayOf(nelsonType, dimsVector.getElementCount());
- double* ptrRes = (double*)ptr;
ArrayOf res = ArrayOf(nelsonType, dimsVector, ptr);
-
+ double* ptrRes = (double*)ptr;
for (Py_ssize_t i = 0; i < vectorSize; ++i) {
PyObject* item = NLSPySequence_GetItem(pyObject, i);
ptrRes[i] = NLSPyFloat_AsDouble(item);
diff --git a/modules/python_engine/src/cpp/PythonTypesWrapper.hpp b/modules/python_engine/src/cpp/PythonTypesWrapper.hpp
index f1683dee1a..d60acd66c3 100644
--- a/modules/python_engine/src/cpp/PythonTypesWrapper.hpp
+++ b/modules/python_engine/src/cpp/PythonTypesWrapper.hpp
@@ -27,12 +27,8 @@ arrayToMemoryView(const void* data, NelsonType nelsonType, const Dimensions& dim
PyObject*
arrayOfToPyObject(const ArrayOf& A);
//=============================================================================
-PyObject*
-PyArgsArrayOfToPyObject(const ArrayOf& A);
-//=============================================================================
ArrayOf
PyMemoryViewToArrayOf(PyObject* pyObject);
//=============================================================================
-
}
//=============================================================================
diff --git a/modules/python_engine/src/include/PythonConfig.hpp b/modules/python_engine/src/include/PythonConfig.hpp
index 8ecbbed6f2..e22ad9bdaf 100644
--- a/modules/python_engine/src/include/PythonConfig.hpp
+++ b/modules/python_engine/src/include/PythonConfig.hpp
@@ -18,4 +18,7 @@
#undef PyComplex_Type
#undef PyFloat_Type
#undef PyNone
+#undef PyBytes_Type
+#undef PyLong_Type
+#undef PyByteArray_Type
//=============================================================================
diff --git a/modules/python_engine/src/include/PythonObjectHandle.hpp b/modules/python_engine/src/include/PythonObjectHandle.hpp
index be0f825963..db0820120a 100644
--- a/modules/python_engine/src/include/PythonObjectHandle.hpp
+++ b/modules/python_engine/src/include/PythonObjectHandle.hpp
@@ -59,6 +59,8 @@ class NLSPYTHON_ENGINE_IMPEXP PythonObjectHandle : public HandleGenericObject
isMainPythonInterpreter();
//=============================================================================
private:
+ //=============================================================================
+ wstringVector methodCastNames;
//=============================================================================
wstringVector
getCastMethods();
@@ -67,6 +69,9 @@ class NLSPYTHON_ENGINE_IMPEXP PythonObjectHandle : public HandleGenericObject
isCastMethod(const std::wstring& methodName);
//=============================================================================
bool
+ isPyObjectMethod(const std::wstring& methodName);
+ //=============================================================================
+ bool
invokeCastMethod(const std::wstring& methodName, ArrayOfVector& results);
//=============================================================================
using MethodMap = std::map>;
diff --git a/modules/python_engine/tests/test_type_None.m b/modules/python_engine/tests/test_type_None.m
new file mode 100644
index 0000000000..97f386abd5
--- /dev/null
+++ b/modules/python_engine/tests/test_type_None.m
@@ -0,0 +1,26 @@
+%=============================================================================
+% Copyright (c) 2016-present Allan CORNET (Nelson)
+%=============================================================================
+% This file is part of the Nelson.
+%=============================================================================
+% LICENCE_BLOCK_BEGIN
+% SPDX-License-Identifier: LGPL-3.0-or-later
+% LICENCE_BLOCK_END
+%=============================================================================
+% <--PYTHON ENVIRONMENT REQUIRED-->
+%=============================================================================
+R = pyrun('P = None', "P");
+assert_isequal(class(R), 'py.NoneType');
+assert_isequal(R.char, 'None');
+assert_checkerror('R.struct()', _('Wrong value for #2 argument. struct'));
+assert_checkerror('R.cell()', _('Wrong value for #2 argument. cell'));
+assert_checkerror('R.int8()', _('Wrong value for #2 argument. int8'));
+assert_checkerror('R.int16()', _('Wrong value for #2 argument. int16'));
+assert_checkerror('R.int32()', _('Wrong value for #2 argument. int32'));
+assert_checkerror('R.int64()', _('Wrong value for #2 argument. int64'));
+assert_checkerror('R.uint8()', _('Wrong value for #2 argument. uint8'));
+assert_checkerror('R.uint16()', _('Wrong value for #2 argument. uint16'));
+assert_checkerror('R.uint32()', _('Wrong value for #2 argument. uint32'));
+assert_checkerror('R.uint64()', _('Wrong value for #2 argument. uint64'));
+assert_checkerror('R.single()', _('Wrong value for #2 argument. single'));
+assert_checkerror('R.double()', _('Wrong value for #2 argument. double'));
diff --git a/modules/python_engine/tests/test_type_arrayarray.m b/modules/python_engine/tests/test_type_arrayarray.m
new file mode 100644
index 0000000000..7a9ee22389
--- /dev/null
+++ b/modules/python_engine/tests/test_type_arrayarray.m
@@ -0,0 +1,167 @@
+%=============================================================================
+% Copyright (c) 2016-present Allan CORNET (Nelson)
+%=============================================================================
+% This file is part of the Nelson.
+%=============================================================================
+% LICENCE_BLOCK_BEGIN
+% SPDX-License-Identifier: LGPL-3.0-or-later
+% LICENCE_BLOCK_END
+%=============================================================================
+% <--PYTHON ENVIRONMENT REQUIRED-->
+%=============================================================================
+R = pyrun("", 'A', 'A', [1 2 3]);
+assert_isequal(R.char(), 'array(''d'', [1.0, 2.0, 3.0])');
+assert_isequal(R.double(), [1 2 3])
+assert_isequal(R.single(), single([1 2 3]))
+assert_isequal(R.int8(), int8([1 2 3]))
+assert_isequal(R.int16(), int16([1 2 3]))
+assert_isequal(R.int32(), int32([1 2 3]))
+assert_isequal(R.int64(), int64([1 2 3]))
+assert_isequal(R.uint8(), uint8([1 2 3]))
+assert_isequal(R.uint16(), uint16([1 2 3]))
+assert_isequal(R.uint32(), uint32([1 2 3]))
+assert_isequal(R.uint64(), uint64([1 2 3]))
+%=============================================================================
+R = pyrun("", 'A', 'A', single([1 2 3]));
+assert_isequal(R.char(), 'array(''f'', [1.0, 2.0, 3.0])');
+assert_isequal(R.double(), [1 2 3])
+assert_isequal(R.single(), single([1 2 3]))
+assert_isequal(R.int8(), int8([1 2 3]))
+assert_isequal(R.int16(), int16([1 2 3]))
+assert_isequal(R.int32(), int32([1 2 3]))
+assert_isequal(R.int64(), int64([1 2 3]))
+assert_isequal(R.uint8(), uint8([1 2 3]))
+assert_isequal(R.uint16(), uint16([1 2 3]))
+assert_isequal(R.uint32(), uint32([1 2 3]))
+assert_isequal(R.uint64(), uint64([1 2 3]))
+%=============================================================================
+R = pyrun("", 'A', 'A', int8([1 2 3]));
+assert_isequal(R.char(), 'array(''b'', [1, 2, 3])');
+assert_isequal(R.double(), [1 2 3])
+assert_isequal(R.single(), single([1 2 3]))
+assert_isequal(R.int8(), int8([1 2 3]))
+assert_isequal(R.int16(), int16([1 2 3]))
+assert_isequal(R.int32(), int32([1 2 3]))
+assert_isequal(R.int64(), int64([1 2 3]))
+assert_isequal(R.uint8(), uint8([1 2 3]))
+assert_isequal(R.uint16(), uint16([1 2 3]))
+assert_isequal(R.uint32(), uint32([1 2 3]))
+assert_isequal(R.uint64(), uint64([1 2 3]))
+%=============================================================================
+R = pyrun("", 'A', 'A', int16([1 2 3]));
+assert_isequal(R.char(), 'array(''h'', [1, 2, 3])');
+assert_isequal(R.double(), [1 2 3])
+assert_isequal(R.single(), single([1 2 3]))
+assert_isequal(R.int8(), int8([1 2 3]))
+assert_isequal(R.int16(), int16([1 2 3]))
+assert_isequal(R.int32(), int32([1 2 3]))
+assert_isequal(R.int64(), int64([1 2 3]))
+assert_isequal(R.uint8(), uint8([1 2 3]))
+assert_isequal(R.uint16(), uint16([1 2 3]))
+assert_isequal(R.uint32(), uint32([1 2 3]))
+assert_isequal(R.uint64(), uint64([1 2 3]))
+%=============================================================================
+R = pyrun("", 'A', 'A', int32([1 2 3]));
+assert_isequal(R.char(), 'array(''i'', [1, 2, 3])');
+assert_isequal(R.double(), [1 2 3])
+assert_isequal(R.single(), single([1 2 3]))
+assert_isequal(R.int8(), int8([1 2 3]))
+assert_isequal(R.int16(), int16([1 2 3]))
+assert_isequal(R.int32(), int32([1 2 3]))
+assert_isequal(R.int64(), int64([1 2 3]))
+assert_isequal(R.uint8(), uint8([1 2 3]))
+assert_isequal(R.uint16(), uint16([1 2 3]))
+assert_isequal(R.uint32(), uint32([1 2 3]))
+assert_isequal(R.uint64(), uint64([1 2 3]))
+%=============================================================================
+R = pyrun("", 'A', 'A', int64([1 2 3]));
+assert_isequal(R.char(), 'array(''q'', [1, 2, 3])');
+assert_isequal(R.double(), [1 2 3])
+assert_isequal(R.single(), single([1 2 3]))
+assert_isequal(R.int8(), int8([1 2 3]))
+assert_isequal(R.int16(), int16([1 2 3]))
+assert_isequal(R.int32(), int32([1 2 3]))
+assert_isequal(R.int64(), int64([1 2 3]))
+assert_isequal(R.uint8(), uint8([1 2 3]))
+assert_isequal(R.uint16(), uint16([1 2 3]))
+assert_isequal(R.uint32(), uint32([1 2 3]))
+assert_isequal(R.uint64(), uint64([1 2 3]))
+%=============================================================================
+R = pyrun("", 'A', 'A', uint8([1 2 3]));
+assert_isequal(R.char(), 'array(''B'', [1, 2, 3])');
+assert_isequal(R.double(), [1 2 3])
+assert_isequal(R.single(), single([1 2 3]))
+assert_isequal(R.int8(), int8([1 2 3]))
+assert_isequal(R.int16(), int16([1 2 3]))
+assert_isequal(R.int32(), int32([1 2 3]))
+assert_isequal(R.int64(), int64([1 2 3]))
+assert_isequal(R.uint8(), uint8([1 2 3]))
+assert_isequal(R.uint16(), uint16([1 2 3]))
+assert_isequal(R.uint32(), uint32([1 2 3]))
+assert_isequal(R.uint64(), uint64([1 2 3]))
+%=============================================================================
+R = pyrun("", 'A', 'A', uint16([1 2 3]));
+assert_isequal(R.char(), 'array(''H'', [1, 2, 3])');
+assert_isequal(R.double(), [1 2 3])
+assert_isequal(R.single(), single([1 2 3]))
+assert_isequal(R.int8(), int8([1 2 3]))
+assert_isequal(R.int16(), int16([1 2 3]))
+assert_isequal(R.int32(), int32([1 2 3]))
+assert_isequal(R.int64(), int64([1 2 3]))
+assert_isequal(R.uint8(), uint8([1 2 3]))
+assert_isequal(R.uint16(), uint16([1 2 3]))
+assert_isequal(R.uint32(), uint32([1 2 3]))
+assert_isequal(R.uint64(), uint64([1 2 3]))
+%=============================================================================
+R = pyrun("", 'A', 'A', uint32([1 2 3]));
+assert_isequal(R.char(), 'array(''I'', [1, 2, 3])');
+assert_isequal(R.double(), [1 2 3])
+assert_isequal(R.single(), single([1 2 3]))
+assert_isequal(R.int8(), int8([1 2 3]))
+assert_isequal(R.int16(), int16([1 2 3]))
+assert_isequal(R.int32(), int32([1 2 3]))
+assert_isequal(R.int64(), int64([1 2 3]))
+assert_isequal(R.uint8(), uint8([1 2 3]))
+assert_isequal(R.uint16(), uint16([1 2 3]))
+assert_isequal(R.uint32(), uint32([1 2 3]))
+assert_isequal(R.uint64(), uint64([1 2 3]))
+%=============================================================================
+R = pyrun("", 'A', 'A', uint64([1 2 3]));
+assert_isequal(R.char(), 'array(''Q'', [1, 2, 3])');
+assert_isequal(R.double(), [1 2 3])
+assert_isequal(R.single(), single([1 2 3]))
+assert_isequal(R.int8(), int8([1 2 3]))
+assert_isequal(R.int16(), int16([1 2 3]))
+assert_isequal(R.int32(), int32([1 2 3]))
+assert_isequal(R.int64(), int64([1 2 3]))
+assert_isequal(R.uint8(), uint8([1 2 3]))
+assert_isequal(R.uint16(), uint16([1 2 3]))
+assert_isequal(R.uint32(), uint32([1 2 3]))
+assert_isequal(R.uint64(), uint64([1 2 3]))
+%=============================================================================
+R = pyrun("", 'A', 'A', []);
+assert_isequal(R.char, 'array(''d'')')
+assert_isequal(R.double(), zeros(1, 0))
+assert_isequal(R.single(), single(zeros(1, 0)))
+assert_isequal(R.int8(), int8(zeros(1, 0)))
+assert_isequal(R.int16(), int16(zeros(1, 0)))
+assert_isequal(R.int32(), int32(zeros(1, 0)))
+assert_isequal(R.int64(), int64(zeros(1, 0)))
+assert_isequal(R.uint8(), uint8(zeros(1, 0)))
+assert_isequal(R.uint16(), uint16(zeros(1, 0)))
+assert_isequal(R.uint32(), uint32(zeros(1, 0)))
+assert_isequal(R.uint64(), uint64(zeros(1, 0)))
+%=============================================================================
+R = pyrun("", 'A', 'A', single([]));
+assert_isequal(R.char, 'array(''f'')')
+assert_isequal(R.double(), zeros(1, 0))
+assert_isequal(R.single(), single(zeros(1, 0)))
+assert_isequal(R.int8(), int8(zeros(1, 0)))
+assert_isequal(R.int16(), int16(zeros(1, 0)))
+assert_isequal(R.int32(), int32(zeros(1, 0)))
+assert_isequal(R.int64(), int64(zeros(1, 0)))
+assert_isequal(R.uint8(), uint8(zeros(1, 0)))
+assert_isequal(R.uint16(), uint16(zeros(1, 0)))
+assert_isequal(R.uint32(), uint32(zeros(1, 0)))
+assert_isequal(R.uint64(), uint64(zeros(1, 0)))
+%=============================================================================
diff --git a/modules/python_engine/tests/test_type_boolean.m b/modules/python_engine/tests/test_type_boolean.m
new file mode 100644
index 0000000000..a0b1352319
--- /dev/null
+++ b/modules/python_engine/tests/test_type_boolean.m
@@ -0,0 +1,18 @@
+%=============================================================================
+% Copyright (c) 2016-present Allan CORNET (Nelson)
+%=============================================================================
+% This file is part of the Nelson.
+%=============================================================================
+% LICENCE_BLOCK_BEGIN
+% SPDX-License-Identifier: LGPL-3.0-or-later
+% LICENCE_BLOCK_END
+%=============================================================================
+% <--PYTHON ENVIRONMENT REQUIRED-->
+%=============================================================================
+R = pyrun('R = True', "R");
+assert_isequal(class(R), 'logical');
+assert_isequal(R, true);
+%=============================================================================
+R = pyrun('R = False', "R");
+assert_isequal(R, false);
+%=============================================================================
diff --git a/modules/python_engine/tests/test_type_bytes.m b/modules/python_engine/tests/test_type_bytes.m
new file mode 100644
index 0000000000..9c23696920
--- /dev/null
+++ b/modules/python_engine/tests/test_type_bytes.m
@@ -0,0 +1,33 @@
+%=============================================================================
+% Copyright (c) 2016-present Allan CORNET (Nelson)
+%=============================================================================
+% This file is part of the Nelson.
+%=============================================================================
+% LICENCE_BLOCK_BEGIN
+% SPDX-License-Identifier: LGPL-3.0-or-later
+% LICENCE_BLOCK_END
+%=============================================================================
+% <--PYTHON ENVIRONMENT REQUIRED-->
+%=============================================================================
+R = pyrun("message = 'Python is fun';byte_message = bytes(message, 'utf-8')", "byte_message");
+%=============================================================================
+REF = [80 121 116 104 111 110 32 105 115 32 102 117 110];
+%=============================================================================
+assert_isequal(class(R), 'py.bytes');
+assert_isequal(double(R), REF);
+assert_isequal(R.double, REF);
+%=============================================================================
+assert_isequal(R.char(), 'b''Python is fun''');
+assert_isequal(R.int8(), int8(REF));
+assert_isequal(R.int16(), int16(REF));
+assert_isequal(R.int32(), int32(REF));
+assert_isequal(R.int64(), int64(REF));
+assert_isequal(R.uint8(), uint8(REF));
+assert_isequal(R.uint16(), uint16(REF));
+assert_isequal(R.uint32(), uint32(REF));
+assert_isequal(R.uint64(), uint64(REF));
+assert_isequal(R.single(), single(REF));
+assert_checkerror('R.struct()', _('Wrong value for #2 argument. struct'));
+assert_checkerror('R.string()', _('Wrong value for #2 argument. string'));
+%=============================================================================
+
diff --git a/modules/python_engine/tests/test_type_bytesarray.m b/modules/python_engine/tests/test_type_bytesarray.m
new file mode 100644
index 0000000000..038e50d987
--- /dev/null
+++ b/modules/python_engine/tests/test_type_bytesarray.m
@@ -0,0 +1,26 @@
+%=============================================================================
+% Copyright (c) 2016-present Allan CORNET (Nelson)
+%=============================================================================
+% This file is part of the Nelson.
+%=============================================================================
+% LICENCE_BLOCK_BEGIN
+% SPDX-License-Identifier: LGPL-3.0-or-later
+% LICENCE_BLOCK_END
+%=============================================================================
+% <--PYTHON ENVIRONMENT REQUIRED-->
+%=============================================================================
+R = pyrun('prime_numbers = [2, 3, 5, 7]; byte_array = bytearray(prime_numbers)', "byte_array");
+assert_isequal(class(R), 'py.bytearray');
+assert_isequal(R.int8(), int8([2, 3, 5, 7]));
+assert_isequal(R.int16(), int16([2, 3, 5, 7]));
+assert_isequal(R.int32(), int32([2, 3, 5, 7]));
+assert_isequal(R.int64(), int64([2, 3, 5, 7]));
+assert_isequal(R.uint8(), uint8([2, 3, 5, 7]));
+assert_isequal(R.uint16(), uint16([2, 3, 5, 7]));
+assert_isequal(R.uint32(), uint32([2, 3, 5, 7]));
+assert_isequal(R.uint64(), uint64([2, 3, 5, 7]));
+assert_isequal(R.single(), single([2, 3, 5, 7]));
+assert_isequal(R.double(), double([2, 3, 5, 7]));
+assert_isequal(R.char(), 'bytearray(b''\x02\x03\x05\x07'')');
+assert_checkerror('R.struct()', _('Wrong value for #2 argument. struct'));
+%=============================================================================
\ No newline at end of file
diff --git a/modules/python_engine/tests/test_type_complex.m b/modules/python_engine/tests/test_type_complex.m
new file mode 100644
index 0000000000..417035f10a
--- /dev/null
+++ b/modules/python_engine/tests/test_type_complex.m
@@ -0,0 +1,14 @@
+%=============================================================================
+% Copyright (c) 2016-present Allan CORNET (Nelson)
+%=============================================================================
+% This file is part of the Nelson.
+%=============================================================================
+% LICENCE_BLOCK_BEGIN
+% SPDX-License-Identifier: LGPL-3.0-or-later
+% LICENCE_BLOCK_END
+%=============================================================================
+% <--PYTHON ENVIRONMENT REQUIRED-->
+%=============================================================================
+R = pyrun('R = complex(3, 2)', "R");
+assert_isequal(R, 3+2i);
+%=============================================================================
diff --git a/modules/python_engine/tests/test_type_dict.m b/modules/python_engine/tests/test_type_dict.m
new file mode 100644
index 0000000000..3c93f9c307
--- /dev/null
+++ b/modules/python_engine/tests/test_type_dict.m
@@ -0,0 +1,27 @@
+%=============================================================================
+% Copyright (c) 2016-present Allan CORNET (Nelson)
+%=============================================================================
+% This file is part of the Nelson.
+%=============================================================================
+% LICENCE_BLOCK_BEGIN
+% SPDX-License-Identifier: LGPL-3.0-or-later
+% LICENCE_BLOCK_END
+%=============================================================================
+% <--PYTHON ENVIRONMENT REQUIRED-->
+%=============================================================================
+R = pyrun('R = {}', "R");
+assert_isequal(R.char(), '{}');
+%=============================================================================
+R = pyrun("R = {'name': 'Dionysia', 'age': 28, 'location': 'Athens'}", "R");
+assert_checkerror('R.cell', _('Wrong value for #2 argument. cell'))
+assert_isequal(R.char(), '{''name'': ''Dionysia'', ''age'': 28, ''location'': ''Athens''}')
+%=============================================================================
+st = R.struct();
+assert_isequal(fieldnames(st), {'name'; 'age'; 'location'})
+assert_isequal(class(st.name), 'py.str');
+assert_isequal(st.name.char, 'Dionysia');
+assert_isequal(class(st.age), 'py.int');
+assert_isequal(st.age.double, 28);
+assert_isequal(class(st.location), 'py.str');
+assert_isequal(st.location.char, 'Athens');
+%=============================================================================
\ No newline at end of file
diff --git a/modules/python_engine/tests/test_type_float.m b/modules/python_engine/tests/test_type_float.m
new file mode 100644
index 0000000000..236e5db302
--- /dev/null
+++ b/modules/python_engine/tests/test_type_float.m
@@ -0,0 +1,14 @@
+%=============================================================================
+% Copyright (c) 2016-present Allan CORNET (Nelson)
+%=============================================================================
+% This file is part of the Nelson.
+%=============================================================================
+% LICENCE_BLOCK_BEGIN
+% SPDX-License-Identifier: LGPL-3.0-or-later
+% LICENCE_BLOCK_END
+%=============================================================================
+% <--PYTHON ENVIRONMENT REQUIRED-->
+%=============================================================================
+R = pyrun('R = 3.2', "R");
+assert_isequal(R, 3.2);
+%=============================================================================
diff --git a/modules/python_engine/tests/test_type_int.m b/modules/python_engine/tests/test_type_int.m
new file mode 100644
index 0000000000..2b8edba6a3
--- /dev/null
+++ b/modules/python_engine/tests/test_type_int.m
@@ -0,0 +1,29 @@
+%=============================================================================
+% Copyright (c) 2016-present Allan CORNET (Nelson)
+%=============================================================================
+% This file is part of the Nelson.
+%=============================================================================
+% LICENCE_BLOCK_BEGIN
+% SPDX-License-Identifier: LGPL-3.0-or-later
+% LICENCE_BLOCK_END
+%=============================================================================
+% <--PYTHON ENVIRONMENT REQUIRED-->
+%=============================================================================
+R = pyrun('P = 3', "P");
+assert_isequal(class(R), 'py.int');
+assert_isequal(R.char, '3');
+assert_isequal(R.int8(), int8(3));
+assert_isequal(R.int16(), int16(3));
+assert_isequal(R.int32(), int32(3));
+assert_isequal(R.int64(), int64(3));
+assert_isequal(R.uint8(), uint8(3));
+assert_isequal(R.uint16(), uint16(3));
+assert_isequal(R.uint32(), uint32(3));
+assert_isequal(R.uint64(), uint64(3));
+assert_isequal(R.single(), single(3));
+assert_isequal(R.double(), double(3));
+%=============================================================================
+assert_checkerror('R.cell()', _('Wrong value for #2 argument. cell'));
+assert_checkerror('R.struct()', _('Wrong value for #2 argument. struct'));
+assert_checkerror('R.numeric()', _('Wrong value for #2 argument. numeric'));
+%=============================================================================
diff --git a/modules/python_engine/tests/test_type_list.m b/modules/python_engine/tests/test_type_list.m
new file mode 100644
index 0000000000..04146eb6ce
--- /dev/null
+++ b/modules/python_engine/tests/test_type_list.m
@@ -0,0 +1,40 @@
+%=============================================================================
+% Copyright (c) 2016-present Allan CORNET (Nelson)
+%=============================================================================
+% This file is part of the Nelson.
+%=============================================================================
+% LICENCE_BLOCK_BEGIN
+% SPDX-License-Identifier: LGPL-3.0-or-later
+% LICENCE_BLOCK_END
+%=============================================================================
+% <--PYTHON ENVIRONMENT REQUIRED-->
+%=============================================================================
+R = pyrun("A = [1, 2, 3, 4]", 'A');
+assert_isequal(class(R), 'py.list')
+RC = R.cell();
+assert_isequal(size(RC), [1, 4])
+assert_isequal(RC{1}.double(), 1);
+assert_isequal(RC{2}.double(), 2);
+assert_isequal(RC{3}.double(), 3);
+assert_isequal(RC{4}.double(), 4);
+%=============================================================================
+assert_isequal(R.double(), double([1, 2, 3, 4]))
+%=============================================================================
+assert_isequal(R.string(), ["1", "2", "3", "4"])
+%=============================================================================
+assert_isequal(R.single(), single([1, 2, 3, 4]))
+%=============================================================================
+assert_isequal(R.int8(), int8([1, 2, 3, 4]))
+assert_isequal(R.int16(), int16([1, 2, 3, 4]))
+assert_isequal(R.int32(), int32([1, 2, 3, 4]))
+assert_isequal(R.int64(), int64([1, 2, 3, 4]))
+%=============================================================================
+assert_isequal(R.uint8(), uint8([1, 2, 3, 4]))
+assert_isequal(R.uint16(), uint16([1, 2, 3, 4]))
+assert_isequal(R.uint32(), uint32([1, 2, 3, 4]))
+assert_isequal(R.uint64(), uint64([1, 2, 3, 4]))
+%=============================================================================
+R = pyrun("A = [1, '2', 3, 4]", 'A');
+assert_isequal(R.string(), ["1", "2", "3", "4"])
+assert_checkerror('R.double()', _('All Python elements must be convertible as scalar to the requested type.'))
+%=============================================================================
diff --git a/modules/python_engine/tests/test_type_memoryview.m b/modules/python_engine/tests/test_type_memoryview.m
new file mode 100644
index 0000000000..a1b1c9a8bc
--- /dev/null
+++ b/modules/python_engine/tests/test_type_memoryview.m
@@ -0,0 +1,166 @@
+%=============================================================================
+% Copyright (c) 2016-present Allan CORNET (Nelson)
+%=============================================================================
+% This file is part of the Nelson.
+%=============================================================================
+% LICENCE_BLOCK_BEGIN
+% SPDX-License-Identifier: LGPL-3.0-or-later
+% LICENCE_BLOCK_END
+%=============================================================================
+% <--PYTHON ENVIRONMENT REQUIRED-->
+%=============================================================================
+R = pyrun("", "P",'P', [1 2; 3 4]);
+REF = [1 2; 3 4];
+assert_isequal(R.double, REF);
+assert_isequal(R.single, single(REF));
+assert_isequal(R.int8(), int8(REF));
+assert_isequal(R.int16(), int16(REF));
+assert_isequal(R.int32(), int32(REF));
+assert_isequal(R.int64(), int64(REF));
+assert_isequal(R.uint8(), uint8(REF));
+assert_isequal(R.uint16(), uint16(REF));
+assert_isequal(R.uint32(), uint32(REF));
+assert_isequal(R.uint64(), uint64(REF));
+assert_checkerror('R.cell()', _('Cannot convert to cell'));
+%=============================================================================
+R = pyrun("", 'A', 'A', [1 2; 3 4]);
+assert_isequal(class(R), 'py.memoryview')
+assert_isequal(R.format.char, 'd');
+assert_isequal(R.double, [1 2; 3 4])
+%=============================================================================
+R = pyrun("", 'A', 'A', single([1 2; 3 4]));
+assert_isequal(class(R), 'py.memoryview')
+assert_isequal(R.format.char, 'f');
+assert_isequal(R.double, [1 2; 3 4])
+%=============================================================================
+
+R = pyrun("", 'A', 'A', [1 2 3]+i);
+assert_isequal(class(R), 'py.memoryview')
+assert_isequal(R.format.char, 'Zd');
+assert_isequal(R.double, [1 2 3]+i)
+%=============================================================================
+R = pyrun("", 'A', 'A', single([1 2 3]+i));
+assert_isequal(class(R), 'py.memoryview')
+assert_isequal(R.format.char, 'Zf');
+assert_isequal(R.double, [1 2 3]+i)
+%=============================================================================
+A = int8([1 2; 3 4]);
+R = pyrun("", "P",'P', A);
+REF = A;
+assert_isequal(R.double, double(REF));
+assert_isequal(R.single, single(REF));
+assert_isequal(R.int8(), int8(REF));
+assert_isequal(R.int16(), int16(REF));
+assert_isequal(R.int32(), int32(REF));
+assert_isequal(R.int64(), int64(REF));
+assert_isequal(R.uint8(), uint8(REF));
+assert_isequal(R.uint16(), uint16(REF));
+assert_isequal(R.uint32(), uint32(REF));
+assert_isequal(R.uint64(), uint64(REF));
+assert_checkerror('R.cell()', _('Cannot convert to cell'));
+%=============================================================================
+A = int16([1 2; 3 4]);
+R = pyrun("", "P",'P', A);
+REF = A;
+assert_isequal(R.double, double(REF));
+assert_isequal(R.single, single(REF));
+assert_isequal(R.int8(), int8(REF));
+assert_isequal(R.int16(), int16(REF));
+assert_isequal(R.int32(), int32(REF));
+assert_isequal(R.int64(), int64(REF));
+assert_isequal(R.uint8(), uint8(REF));
+assert_isequal(R.uint16(), uint16(REF));
+assert_isequal(R.uint32(), uint32(REF));
+assert_isequal(R.uint64(), uint64(REF));
+assert_checkerror('R.cell()', _('Cannot convert to cell'));
+%=============================================================================
+A = int32([1 2; 3 4]);
+R = pyrun("", "P",'P', A);
+REF = A;
+assert_isequal(R.double, double(REF));
+assert_isequal(R.single, single(REF));
+assert_isequal(R.int8(), int8(REF));
+assert_isequal(R.int16(), int16(REF));
+assert_isequal(R.int32(), int32(REF));
+assert_isequal(R.int64(), int64(REF));
+assert_isequal(R.uint8(), uint8(REF));
+assert_isequal(R.uint16(), uint16(REF));
+assert_isequal(R.uint32(), uint32(REF));
+assert_isequal(R.uint64(), uint64(REF));
+assert_checkerror('R.cell()', _('Cannot convert to cell'));
+%=============================================================================
+A = int64([1 2; 3 4]);
+R = pyrun("", "P",'P', A);
+REF = A;
+assert_isequal(R.double, double(REF));
+assert_isequal(R.single, single(REF));
+assert_isequal(R.int8(), int8(REF));
+assert_isequal(R.int16(), int16(REF));
+assert_isequal(R.int32(), int32(REF));
+assert_isequal(R.int64(), int64(REF));
+assert_isequal(R.uint8(), uint8(REF));
+assert_isequal(R.uint16(), uint16(REF));
+assert_isequal(R.uint32(), uint32(REF));
+assert_isequal(R.uint64(), uint64(REF));
+assert_checkerror('R.cell()', _('Cannot convert to cell'));
+%=============================================================================
+A = uint8([1 2; 3 4]);
+R = pyrun("", "P",'P', A);
+REF = A;
+assert_isequal(R.double, double(REF));
+assert_isequal(R.single, single(REF));
+assert_isequal(R.int8(), int8(REF));
+assert_isequal(R.int16(), int16(REF));
+assert_isequal(R.int32(), int32(REF));
+assert_isequal(R.int64(), int64(REF));
+assert_isequal(R.uint8(), uint8(REF));
+assert_isequal(R.uint16(), uint16(REF));
+assert_isequal(R.uint32(), uint32(REF));
+assert_isequal(R.uint64(), uint64(REF));
+assert_checkerror('R.cell()', _('Cannot convert to cell'));
+%=============================================================================
+A = uint16([1 2; 3 4]);
+R = pyrun("", "P",'P', A);
+REF = A;
+assert_isequal(R.double, double(REF));
+assert_isequal(R.single, single(REF));
+assert_isequal(R.int8(), int8(REF));
+assert_isequal(R.int16(), int16(REF));
+assert_isequal(R.int32(), int32(REF));
+assert_isequal(R.int64(), int64(REF));
+assert_isequal(R.uint8(), uint8(REF));
+assert_isequal(R.uint16(), uint16(REF));
+assert_isequal(R.uint32(), uint32(REF));
+assert_isequal(R.uint64(), uint64(REF));
+assert_checkerror('R.cell()', _('Cannot convert to cell'));
+%=============================================================================
+A = uint32([1 2; 3 4]);
+R = pyrun("", "P",'P', A);
+REF = A;
+assert_isequal(R.double, double(REF));
+assert_isequal(R.single, single(REF));
+assert_isequal(R.int8(), int8(REF));
+assert_isequal(R.int16(), int16(REF));
+assert_isequal(R.int32(), int32(REF));
+assert_isequal(R.int64(), int64(REF));
+assert_isequal(R.uint8(), uint8(REF));
+assert_isequal(R.uint16(), uint16(REF));
+assert_isequal(R.uint32(), uint32(REF));
+assert_isequal(R.uint64(), uint64(REF));
+assert_checkerror('R.cell()', _('Cannot convert to cell'));
+%=============================================================================
+A = uint64([1 2; 3 4]);
+R = pyrun("", "P",'P', A);
+REF = A;
+assert_isequal(R.double, double(REF));
+assert_isequal(R.single, single(REF));
+assert_isequal(R.int8(), int8(REF));
+assert_isequal(R.int16(), int16(REF));
+assert_isequal(R.int32(), int32(REF));
+assert_isequal(R.int64(), int64(REF));
+assert_isequal(R.uint8(), uint8(REF));
+assert_isequal(R.uint16(), uint16(REF));
+assert_isequal(R.uint32(), uint32(REF));
+assert_isequal(R.uint64(), uint64(REF));
+assert_checkerror('R.cell()', _('Cannot convert to cell'));
+%=============================================================================
diff --git a/modules/python_engine/tests/test_type_str.m b/modules/python_engine/tests/test_type_str.m
new file mode 100644
index 0000000000..89b6c95880
--- /dev/null
+++ b/modules/python_engine/tests/test_type_str.m
@@ -0,0 +1,16 @@
+%=============================================================================
+% Copyright (c) 2016-present Allan CORNET (Nelson)
+%=============================================================================
+% This file is part of the Nelson.
+%=============================================================================
+% LICENCE_BLOCK_BEGIN
+% SPDX-License-Identifier: LGPL-3.0-or-later
+% LICENCE_BLOCK_END
+%=============================================================================
+% <--PYTHON ENVIRONMENT REQUIRED-->
+%=============================================================================
+R = pyrun("R = 'Hello from Python'", "R");
+assert_isequal(R.char, 'Hello from Python');
+assert_isequal(R.string, "Hello from Python");
+assert_checkerror('R.struct()', _('Wrong value for #2 argument. struct'));
+%=============================================================================
diff --git a/modules/python_engine/tests/test_type_tuple.m b/modules/python_engine/tests/test_type_tuple.m
new file mode 100644
index 0000000000..82aeea2493
--- /dev/null
+++ b/modules/python_engine/tests/test_type_tuple.m
@@ -0,0 +1,36 @@
+%=============================================================================
+% Copyright (c) 2016-present Allan CORNET (Nelson)
+%=============================================================================
+% This file is part of the Nelson.
+%=============================================================================
+% LICENCE_BLOCK_BEGIN
+% SPDX-License-Identifier: LGPL-3.0-or-later
+% LICENCE_BLOCK_END
+%=============================================================================
+% <--PYTHON ENVIRONMENT REQUIRED-->
+%=============================================================================
+R = pyrun("A = (1, 2, 3, 4)", 'A');
+assert_isequal(class(R), 'py.tuple')
+assert_isequal(R.char, '(1, 2, 3, 4)')
+RC = R.cell();
+assert_isequal(size(RC), [1, 4])
+assert_isequal(RC{1}.double(), 1);
+assert_isequal(RC{2}.double(), 2);
+assert_isequal(RC{3}.double(), 3);
+assert_isequal(RC{4}.double(), 4);
+%=============================================================================
+assert_isequal(R.double(), double([1, 2, 3, 4]))
+assert_isequal(R.single(), single([1, 2, 3, 4]))
+%=============================================================================
+assert_isequal(R.int8(), int8([1, 2, 3, 4]))
+assert_isequal(R.int16(), int16([1, 2, 3, 4]))
+assert_isequal(R.int32(), int32([1, 2, 3, 4]))
+assert_isequal(R.int64(), int64([1, 2, 3, 4]))
+%=============================================================================
+assert_isequal(R.uint8(), uint8([1, 2, 3, 4]))
+assert_isequal(R.uint16(), uint16([1, 2, 3, 4]))
+assert_isequal(R.uint32(), uint32([1, 2, 3, 4]))
+assert_isequal(R.uint64(), uint64([1, 2, 3, 4]))
+%=============================================================================
+assert_isequal(R.string(), string([1, 2, 3, 4]))
+%=============================================================================
diff --git a/modules/single/src/cpp/ToSingle.cpp b/modules/single/src/cpp/ToSingle.cpp
index 86e834426f..61544e60bb 100644
--- a/modules/single/src/cpp/ToSingle.cpp
+++ b/modules/single/src/cpp/ToSingle.cpp
@@ -69,7 +69,7 @@ ToSingle(const ArrayOf& A, bool& needToOverload)
return ToSingle(A);
} break;
case NLS_INT64: {
- return ToSingle(A);
+ return ToSingle(A);
} break;
case NLS_SCOMPLEX:
case NLS_SINGLE: {
diff --git a/modules/single/tests/test_single.m b/modules/single/tests/test_single.m
new file mode 100644
index 0000000000..ecec67aab8
--- /dev/null
+++ b/modules/single/tests/test_single.m
@@ -0,0 +1,14 @@
+%=============================================================================
+% Copyright (c) 2016-present Allan CORNET (Nelson)
+%=============================================================================
+% This file is part of the Nelson.
+%=============================================================================
+% LICENCE_BLOCK_BEGIN
+% SPDX-License-Identifier: LGPL-3.0-or-later
+% LICENCE_BLOCK_END
+%=============================================================================
+A = int64([1 2; 3 4]);
+R = single(A);
+REF = single([1 2; 3 4]);
+assert_isequal(R, REF);
+%=============================================================================