244 lines
14 KiB
C++
244 lines
14 KiB
C++
/* 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<StreamBuffer> &output,
|
|
const std::shared_ptr<StreamBuffer> &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<void> MATLABEngine::evalAsync(const std::u16string &statement,
|
|
const std::shared_ptr<StreamBuffer> &output,
|
|
const std::shared_ptr<StreamBuffer> &error
|
|
) {
|
|
|
|
std::promise<void>* p = new std::promise<void>();
|
|
std::future<void> f = p->get_future();
|
|
|
|
uintptr_t* handles;
|
|
std::vector<uintptr_t> handlesV(3);
|
|
|
|
void* output_ = output? new std::shared_ptr<StreamBuffer>(std::move(output)) : nullptr;
|
|
void* error_ = error? new std::shared_ptr<StreamBuffer>(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<void>(std::move(f), std::make_shared<TaskReference>(handlesV[0], &cpp_engine_cancel_feval_with_completion));
|
|
}
|
|
|
|
|
|
inline FutureResult<matlab::data::Array> 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<matlab::data::Array> args;
|
|
args.push_back(arg2);
|
|
args.push_back(arg1);
|
|
return fevalAsync(convertUTF8StringToUTF16String("matlab.internal.engine.getVariable"), args, nullptr, nullptr);
|
|
}
|
|
|
|
inline FutureResult<matlab::data::Array> MATLABEngine::getVariableAsync(const std::string &varName, WorkspaceType workspaceType) {
|
|
return getVariableAsync(std::u16string(varName.cbegin(), varName.cend()), workspaceType);
|
|
}
|
|
|
|
inline FutureResult<void> 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<matlab::data::Array> args;
|
|
args.push_back(arg2);
|
|
args.push_back(var);
|
|
args.push_back(arg1);
|
|
size_t nrhs = args.size();
|
|
std::unique_ptr<matlab::data::impl::ArrayImpl*, void(*)(matlab::data::impl::ArrayImpl**)> 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<matlab::data::impl::ArrayImpl>(e);
|
|
}
|
|
std::promise<void>* p = new std::promise<void>();
|
|
std::future<void> 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<void>(std::move(f), std::make_shared<TaskReference>(handle, &cpp_engine_cancel_feval_with_completion));
|
|
}
|
|
|
|
inline FutureResult<void> 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<matlab::data::Array> 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<matlab::data::Array> 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<matlab::data::Array> MATLABEngine::getPropertyAsync(const matlab::data::Array &object, const std::u16string &propertyName) {
|
|
return getPropertyAsyncImpl(object, 0, propertyName, this, true);
|
|
}
|
|
|
|
inline FutureResult<matlab::data::Array> MATLABEngine::getPropertyAsync(const matlab::data::Array &objectArray, size_t index, const std::u16string &propertyName) {
|
|
return getPropertyAsyncImpl(objectArray, index, propertyName, this, false);
|
|
}
|
|
|
|
inline FutureResult<matlab::data::Array> MATLABEngine::getPropertyAsync(const matlab::data::Array &object, const std::string &propertyName) {
|
|
return getPropertyAsync(object, std::u16string(propertyName.cbegin(), propertyName.cend()));
|
|
}
|
|
|
|
namespace {
|
|
|
|
FutureResult<void> 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<matlab::data::Array> 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<void> ret;
|
|
if (objectArray.getType() == matlab::data::ArrayType::VALUE_OBJECT) {
|
|
FutureResult<matlab::data::Array> f = eng->fevalAsync(convertUTF8StringToUTF16String("matlab.internal.engine.setProperty"), args);
|
|
auto copyableF = std::make_shared<FutureResult<matlab::data::Array>>(std::move(f));
|
|
auto convertToResultType = [&objectArray, copyableF]() {
|
|
matlab::data::Array vec = copyableF->get();
|
|
objectArray = std::move(vec);
|
|
};
|
|
std::future<void> future = std::async(std::launch::deferred, std::move(convertToResultType));
|
|
ret = FutureResult<void>(std::move(future), copyableF->getTaskReference());
|
|
}
|
|
else if (objectArray.getType() == matlab::data::ArrayType::HANDLE_OBJECT_REF) {
|
|
std::unique_ptr<matlab::data::impl::ArrayImpl*, void(*)(matlab::data::impl::ArrayImpl**)> 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<matlab::data::impl::ArrayImpl>(e);
|
|
}
|
|
std::promise<void>* p = new std::promise<void>();
|
|
std::future<void> 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<void>(std::move(f), std::make_shared<TaskReference>(handle, &cpp_engine_cancel_feval_with_completion));
|
|
}
|
|
else {
|
|
throw matlab::engine::EngineException("The input variable is not a MATLAB object.");
|
|
}
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
inline FutureResult<void> 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<matlab::data::Array> 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<void> 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<void> 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<void> 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 */
|