From d8ed104e2e02442662464769f498f4d3103433ff Mon Sep 17 00:00:00 2001 From: Duc Le Date: Sat, 23 Sep 2023 17:11:09 +0100 Subject: [PATCH] Move py fun wrapper to type_conv from libpymcr main --- libpymcr/MatlabProxyObject.py | 9 ++++++--- libpymcr/utils.py | 2 +- src/CMakeLists.txt | 2 +- src/libpymcr.cpp | 17 ++--------------- src/libpymcr.hpp | 1 - src/type_converter.cpp | 10 +++++++--- src/type_converter.hpp | 2 +- 7 files changed, 18 insertions(+), 25 deletions(-) diff --git a/libpymcr/MatlabProxyObject.py b/libpymcr/MatlabProxyObject.py index f16d461..09a64ab 100644 --- a/libpymcr/MatlabProxyObject.py +++ b/libpymcr/MatlabProxyObject.py @@ -73,7 +73,8 @@ def __init__(self, interface, handle): """ self.__dict__['handle'] = handle self.__dict__['interface'] = interface - self.__dict__['_is_handle_class'] = self.interface.call('isa', self.handle, 'handle', nargout=1) + self.__dict__['_methods'] = [] + #self.__dict__['_is_handle_class'] = self.interface.call('isa', self.handle, 'handle', nargout=1) # This cause performance slow downs for large data members and an recursion issue with # samples included in sqw object (each sample object is copied to all dependent header "files") @@ -96,7 +97,9 @@ def _getMethodNames(self): Gets methods from a MATLAB object :return: list of method names """ - return self.interface.call('methods', self.handle) + if not self._methods: + self.__dict__['_methods'] = self.interface.call('methods', self.handle) + return self._methods def __getattr__(self, name): """Retrieve a value or function from the object. @@ -115,7 +118,7 @@ def __getattr__(self, name): except TypeError: return None # if it's a method, wrap it in a functor - elif name in self.interface.call('methods', self.handle, nargout=1): + elif name in self._methods: return matlab_method(self, name) def __setattr__(self, name, value): diff --git a/libpymcr/utils.py b/libpymcr/utils.py index 233cbcf..5c64a5a 100644 --- a/libpymcr/utils.py +++ b/libpymcr/utils.py @@ -71,7 +71,7 @@ def get_branch_of_call(astobj, parent=[]): if rv: parent.append(astobj) return parent - return False + raise SyntaxError('Empty syntax tree') def get_nret_from_call(caller): if isinstance(caller, ast.Call): diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 59c31e0..a35912f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -16,7 +16,7 @@ target_include_directories(call_python PUBLIC ${PYTHON_INCLUDE_DIRS}) target_include_directories(call_python PUBLIC "${pybind11_SOURCE_DIR}/include") ##target_link_libraries(call_python type_converter) ## Explicitly does not link with Matlab libraries (we will call them with dlopen etc) -#set_property(TARGET call_python PROPERTY LINK_LIBRARIES "") +set_property(TARGET call_python PROPERTY LINK_LIBRARIES "") if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") target_link_libraries(call_python ${PYTHON_LIBRARIES}) endif() diff --git a/src/libpymcr.cpp b/src/libpymcr.cpp index 7483d57..c93fecb 100644 --- a/src/libpymcr.cpp +++ b/src/libpymcr.cpp @@ -4,26 +4,13 @@ namespace libpymcr { - matlab::data::Array matlab_env::_conv_to_matlab(PyObject* input) { - matlab::data::Array rv; - if (PyCallable_Check(input)) { - matlab::data::ArrayFactory factory; - std::uintptr_t addr = reinterpret_cast(input); - rv = factory.createStructArray({1, 1}, std::vector({"libpymcr_func_ptr"})); - rv[0][std::string("libpymcr_func_ptr")] = factory.createScalar(addr); - } else { - rv = _converter.to_matlab(input); - } - return rv; - } - size_t matlab_env::_parse_inputs(std::vector& m_args, py::args py_args, py::kwargs& py_kwargs) { matlab::data::ArrayFactory factory; size_t nargout = 1; for (auto item: py_args) { - m_args.push_back(_conv_to_matlab(item.ptr())); + m_args.push_back(_converter.to_matlab(item.ptr())); } for (auto item: py_kwargs) { std::string key(py::str(item.first)); @@ -31,7 +18,7 @@ namespace libpymcr { nargout = item.second.cast(); } else { m_args.push_back(factory.createCharArray(std::string(py::str(item.first)))); - m_args.push_back(_conv_to_matlab(item.second.ptr())); + m_args.push_back(_converter.to_matlab(item.second.ptr())); } } return nargout; diff --git a/src/libpymcr.hpp b/src/libpymcr.hpp index d9080dd..fe6097e 100644 --- a/src/libpymcr.hpp +++ b/src/libpymcr.hpp @@ -21,7 +21,6 @@ namespace libpymcr { std::shared_ptr _m_output_buf = std::static_pointer_cast(_m_output); std::shared_ptr _m_error_buf = std::static_pointer_cast(_m_error); pymat_converter _converter; - matlab::data::Array _conv_to_matlab(PyObject* input); size_t _parse_inputs(std::vector& m_args, py::args py_args, py::kwargs& py_kwargs); public: py::object feval(const std::u16string &funcname, py::args args, py::kwargs& kwargs); diff --git a/src/type_converter.cpp b/src/type_converter.cpp index da9d624..72d11ea 100644 --- a/src/type_converter.cpp +++ b/src/type_converter.cpp @@ -519,9 +519,13 @@ Array pymat_converter::listtuple_to_cell(PyObject *result, matlab::data::ArrayFa } } -matlab::data::Array pymat_converter::wrap_python_function(PyObject *input) { +matlab::data::Array pymat_converter::wrap_python_function(PyObject *input, matlab::data::ArrayFactory &factory) { // Wraps a Python function so it can be called using a mex function - throw std::runtime_error("Python callable conversion requires a custom entry point and mex file"); + matlab::data::Array rv; + std::uintptr_t addr = reinterpret_cast(input); + rv = factory.createStructArray({1, 1}, std::vector({"libpymcr_func_ptr"})); + rv[0][std::string("libpymcr_func_ptr")] = factory.createScalar(addr); + return rv; } matlab::data::Array pymat_converter::python_to_matlab_single(PyObject *input, matlab::data::ArrayFactory &factory) { @@ -548,7 +552,7 @@ matlab::data::Array pymat_converter::python_to_matlab_single(PyObject *input, ma } else if (input == Py_None) { output = factory.createArray({}); } else if (PyCallable_Check(input)) { - output = wrap_python_function(input); + output = wrap_python_function(input, factory); } else if (PyObject_TypeCheck(input, m_py_matlab_wrapper_t)) { output = mArray(reinterpret_cast(input)->arr_impl_sptr); } else { diff --git a/src/type_converter.hpp b/src/type_converter.hpp index f4ac355..a3e4488 100644 --- a/src/type_converter.hpp +++ b/src/type_converter.hpp @@ -161,7 +161,7 @@ namespace libpymcr { CharArray python_string_to_matlab(PyObject *result, matlab::data::ArrayFactory &factory); Array listtuple_to_cell(PyObject *result, matlab::data::ArrayFactory &factory); StructArray python_dict_to_matlab(PyObject *result, matlab::data::ArrayFactory &factory); - matlab::data::Array wrap_python_function(PyObject *input); + matlab::data::Array wrap_python_function(PyObject *input, matlab::data::ArrayFactory &factory); matlab::data::Array python_to_matlab_single(PyObject *input, matlab::data::ArrayFactory &factory); public: void clear_py_cache();