/* Copyright 2017 The MathWorks, Inc. */ #ifndef MATLAB_ENGINE_IMPL_HPP #define MATLAB_ENGINE_IMPL_HPP #include "../matlab_engine.hpp" #include "engine_execution_interface_impl.hpp" #include "engine_exception_impl.hpp" namespace matlab { namespace engine { using namespace matlab::execution; inline MATLABEngine::MATLABEngine(uint64_t handle) : matlab::execution::ExecutionInterface(handle) { } inline void MATLABEngine::eval(const std::u16string &str, const std::shared_ptr &output, const std::shared_ptr &error ) { return evalAsync(str, output, error).get(); } inline matlab::data::Array MATLABEngine::getVariable(const std::u16string &varName, WorkspaceType workspaceType) { return getVariableAsync(varName, workspaceType).get(); } inline matlab::data::Array MATLABEngine::getVariable(const std::string &varName, WorkspaceType workspaceType) { return getVariable(std::u16string(varName.cbegin(), varName.cend()), workspaceType); } inline void MATLABEngine::setVariable(const std::u16string &varName, const matlab::data::Array& var, WorkspaceType workspaceType) { return setVariableAsync(varName, var, workspaceType).get(); } inline void MATLABEngine::setVariable(const std::string &varName, const matlab::data::Array& var, WorkspaceType workspaceType) { return setVariable(std::u16string(varName.cbegin(), varName.cend()), var, workspaceType); } inline matlab::data::Array MATLABEngine::getProperty(const matlab::data::Array &object, const std::u16string &propertyName) { return getPropertyAsync(object, propertyName).get(); } inline matlab::data::Array MATLABEngine::getProperty(const matlab::data::Array &object, const std::string &propertyName) { return getProperty(object, std::u16string(propertyName.cbegin(), propertyName.cend())); } inline matlab::data::Array MATLABEngine::getProperty(const matlab::data::Array &objectArray, size_t index, const std::u16string &propertyName) { return getPropertyAsync(objectArray, index, propertyName).get(); } inline matlab::data::Array MATLABEngine::getProperty(const matlab::data::Array &objectArray, size_t index, const std::string &propertyName) { return getProperty(objectArray, index, std::u16string(propertyName.cbegin(), propertyName.cend())); } inline void MATLABEngine::setProperty(matlab::data::Array &object, const std::u16string &propertyName, const matlab::data::Array &property) { return setPropertyAsync(object, propertyName, property).get(); } inline void MATLABEngine::setProperty(matlab::data::Array &object, const std::string &propertyName, const matlab::data::Array &property) { return setProperty(object, std::u16string(propertyName.cbegin(), propertyName.cend()), property); } inline void MATLABEngine::setProperty(matlab::data::Array &objectArray, size_t index, const std::u16string &propertyName, const matlab::data::Array &property) { return setPropertyAsync(objectArray, index, propertyName, property).get(); } inline void MATLABEngine::setProperty(matlab::data::Array &objectArray, size_t index, const std::string &propertyName, const matlab::data::Array &property) { return setProperty(objectArray, index, std::u16string(propertyName.cbegin(), propertyName.cend()), property); } inline MATLABEngine::~MATLABEngine() { if (matlabHandle != 0) { cpp_engine_terminate_out_of_process_matlab(matlabHandle); matlabHandle = 0; } } inline FutureResult MATLABEngine::evalAsync(const std::u16string &statement, const std::shared_ptr &output, const std::shared_ptr &error ) { std::promise* p = new std::promise(); std::future f = p->get_future(); uintptr_t* handles; std::vector handlesV(3); void* output_ = output? new std::shared_ptr(std::move(output)) : nullptr; void* error_ = error? new std::shared_ptr(std::move(error)) : nullptr; cpp_engine_eval_with_completion(matlabHandle, statement.c_str(), &set_eval_promise_data, &set_eval_promise_exception, p, output_, error_, &writeToStreamBuffer, &deleteStreamBufferImpl, &handles); for (size_t i = 0; i < 3; i++) { handlesV[i] = handles[i]; } cpp_engine_destroy_handles(handles); return FutureResult(std::move(f), std::make_shared(handlesV[0], &cpp_engine_cancel_feval_with_completion)); } inline FutureResult MATLABEngine::getVariableAsync(const std::u16string &varName, WorkspaceType workspaceType) { matlab::data::ArrayFactory factory; const std::string base = (workspaceType == WorkspaceType::BASE) ? std::string("base") : std::string("global"); auto arg1 = factory.createCharArray(base); auto arg2 = factory.createCharArray(varName); std::vector args; args.push_back(arg2); args.push_back(arg1); return fevalAsync(convertUTF8StringToUTF16String("matlab.internal.engine.getVariable"), args, nullptr, nullptr); } inline FutureResult MATLABEngine::getVariableAsync(const std::string &varName, WorkspaceType workspaceType) { return getVariableAsync(std::u16string(varName.cbegin(), varName.cend()), workspaceType); } inline FutureResult MATLABEngine::setVariableAsync(const std::u16string &varName, const matlab::data::Array& var, WorkspaceType workspaceType) { matlab::data::ArrayFactory factory; std::string base = (workspaceType == WorkspaceType::BASE) ? std::string("base") : std::string("global"); auto arg1 = factory.createCharArray(base); auto arg2 = factory.createCharArray(varName); std::vector args; args.push_back(arg2); args.push_back(var); args.push_back(arg1); size_t nrhs = args.size(); std::unique_ptr argsImplPtr(new matlab::data::impl::ArrayImpl*[nrhs], [](matlab::data::impl::ArrayImpl** ptr) { delete[] ptr; }); matlab::data::impl::ArrayImpl** argsImpl = argsImplPtr.get(); size_t i = 0; for (auto e : args) { argsImpl[i++] = matlab::data::detail::Access::getImpl(e); } std::promise* p = new std::promise(); std::future f = p->get_future(); uintptr_t handle = cpp_engine_feval_with_completion(matlabHandle, "matlab.internal.engine.setVariable", 0, true, argsImpl, nrhs, &set_feval_promise_data, &set_feval_promise_exception, p, nullptr, nullptr, &writeToStreamBuffer, &deleteStreamBufferImpl); return FutureResult(std::move(f), std::make_shared(handle, &cpp_engine_cancel_feval_with_completion)); } inline FutureResult MATLABEngine::setVariableAsync(const std::string &varName, const matlab::data::Array& var, WorkspaceType workspaceType) { return setVariableAsync(std::u16string(varName.cbegin(), varName.cend()), var, workspaceType); } namespace { FutureResult getPropertyAsyncImpl(const matlab::data::Array &objectArray, size_t index, const std::u16string &propertyName, matlab::engine::MATLABEngine* eng, bool isScalar) { matlab::data::ArrayFactory factory; auto arg = factory.createCharArray(propertyName); std::vector args; args.push_back(objectArray); if (!isScalar) { args.push_back(factory.createScalar(index + 1)); } args.push_back(arg); return eng->fevalAsync(convertUTF8StringToUTF16String("matlab.internal.engine.getProperty"), args, nullptr, nullptr); } } inline FutureResult MATLABEngine::getPropertyAsync(const matlab::data::Array &object, const std::u16string &propertyName) { return getPropertyAsyncImpl(object, 0, propertyName, this, true); } inline FutureResult MATLABEngine::getPropertyAsync(const matlab::data::Array &objectArray, size_t index, const std::u16string &propertyName) { return getPropertyAsyncImpl(objectArray, index, propertyName, this, false); } inline FutureResult MATLABEngine::getPropertyAsync(const matlab::data::Array &object, const std::string &propertyName) { return getPropertyAsync(object, std::u16string(propertyName.cbegin(), propertyName.cend())); } namespace { FutureResult setPropertyAsyncImpl(matlab::data::Array &objectArray, size_t index, const std::u16string &propertyName, const matlab::data::Array &property, matlab::engine::MATLABEngine* eng, uint64_t engHandle, bool isScalar) { matlab::data::ArrayFactory factory; auto arg = factory.createCharArray(propertyName); std::vector args; args.push_back(objectArray); if (!isScalar) { args.push_back(factory.createScalar(index + 1)); } args.push_back(arg); args.push_back(property); size_t nrhs = args.size(); FutureResult ret; if (objectArray.getType() == matlab::data::ArrayType::VALUE_OBJECT) { FutureResult f = eng->fevalAsync(convertUTF8StringToUTF16String("matlab.internal.engine.setProperty"), args); auto copyableF = std::make_shared>(std::move(f)); auto convertToResultType = [&objectArray, copyableF]() { matlab::data::Array vec = copyableF->get(); objectArray = std::move(vec); }; std::future future = std::async(std::launch::deferred, std::move(convertToResultType)); ret = FutureResult(std::move(future), copyableF->getTaskReference()); } else if (objectArray.getType() == matlab::data::ArrayType::HANDLE_OBJECT_REF) { std::unique_ptr argsImplPtr(new matlab::data::impl::ArrayImpl*[nrhs], [](matlab::data::impl::ArrayImpl** ptr) { delete[] ptr; }); matlab::data::impl::ArrayImpl** argsImpl = argsImplPtr.get();; size_t i = 0; for (auto e : args) { argsImpl[i++] = matlab::data::detail::Access::getImpl(e); } std::promise* p = new std::promise(); std::future f = p->get_future(); uintptr_t handle = cpp_engine_feval_with_completion(engHandle, "matlab.internal.engine.setProperty", 0, true, argsImpl, nrhs, &set_feval_promise_data, &set_feval_promise_exception, p, nullptr, nullptr, &writeToStreamBuffer, &deleteStreamBufferImpl); ret = FutureResult(std::move(f), std::make_shared(handle, &cpp_engine_cancel_feval_with_completion)); } else { throw matlab::engine::EngineException("The input variable is not a MATLAB object."); } return ret; } } inline FutureResult MATLABEngine::setPropertyAsync(matlab::data::Array &object, const std::u16string &propertyName, const matlab::data::Array &property) { return setPropertyAsyncImpl(object, 0, propertyName, property, this, matlabHandle, true); } inline FutureResult MATLABEngine::getPropertyAsync(const matlab::data::Array &objectArray, size_t index, const std::string &propertyName) { return getPropertyAsync(objectArray, index, std::u16string(propertyName.cbegin(), propertyName.cend())); } inline FutureResult MATLABEngine::setPropertyAsync(matlab::data::Array &objectArray, size_t index, const std::u16string &propertyName, const matlab::data::Array &property) { return setPropertyAsyncImpl(objectArray, index, propertyName, property, this, matlabHandle, false); } inline FutureResult MATLABEngine::setPropertyAsync(matlab::data::Array &object, const std::string &propertyName, const matlab::data::Array &property) { return setPropertyAsync(object, std::u16string(propertyName.cbegin(), propertyName.cend()), property); } inline FutureResult MATLABEngine::setPropertyAsync(matlab::data::Array &objectArray, size_t index, const std::string &propertyName, const matlab::data::Array &property) { return setPropertyAsync(objectArray, index, std::u16string(propertyName.cbegin(), propertyName.cend()), property); } } } #endif /* MATLAB_ENGINE_IMPL_HPP */