DYT/Tool/matlab/include/cppmex/detail/mexFunctionAdapterImpl.hpp

163 lines
4.5 KiB
C++
Raw Permalink Normal View History

2024-11-22 15:19:31 +00:00
/* Copyright 2017-2018 The MathWorks, Inc. */
#ifndef __MEX_FUNCTION_ADAPTER_HPP__
#define __MEX_FUNCTION_ADAPTER_HPP__
#include "MatlabDataArray.hpp"
#include "mex.hpp"
#include "mexEngineUtilImpl.hpp"
#include <vector>
#include <iostream>
#include "assert.h"
LIBMWMEX_API_EXTERN_C {
void* cppmex_getEngine(void*);
void* cppmex_mexLock(void*);
void* cppmex_mexUnlock(void*);
void* cppmex_mexLock_with_error_check(void*, int*);
void* cppmex_mexUnlock_with_error_check(void*, int*);
const char16_t* cppmex_getFunctionName(void*);
void mexReleaseMemory(char*, char16_t*);
void* mexGetFunctionImpl();
void mexDestroyFunctionImpl(void*);
}
template <typename T>
matlab::mex::Function * mexCreatorUtil() {
static_assert(std::is_base_of<matlab::mex::Function, T>::value, "MexFunction class must be a subclass of matlab::mex::Function.");
matlab::mex::Function* mexFunction = new T();
return mexFunction;
}
void mexDestructorUtil(matlab::mex::Function * t) {
delete t;
}
void mexHandleException(void (*callbackErrHandler)(const char*, const char*)) {
try {
throw;
} catch(const matlab::engine::MATLABException& ex) {
callbackErrHandler(ex.what(), ex.getMessageID().c_str());
} catch(const matlab::engine::Exception& ex) {
callbackErrHandler(ex.what(), "");
} catch(const matlab::Exception& ex) {
callbackErrHandler(ex.what(), "");
} catch(const std::exception& ex) {
callbackErrHandler(ex.what(), "");
} catch(...) {
callbackErrHandler("Unknown exception thrown.", "");
}
}
class MexFunction;
EXTERN_C
void mexFunction() {}
MEXFUNCTION_LINKAGE
void* mexCreateMexFunction(void (*callbackErrHandler)(const char*, const char*)) {
try {
matlab::mex::Function *mexFunc = mexCreatorUtil<MexFunction>();
return mexFunc;
} catch(...) {
mexHandleException(callbackErrHandler);
return nullptr;
}
}
MEXFUNCTION_LINKAGE
void mexDestroyMexFunction(void* mexFunc,
void (*callbackErrHandler)(const char*, const char*)) {
matlab::mex::Function* mexFunction = reinterpret_cast<matlab::mex::Function*>(mexFunc);
try {
mexDestructorUtil(mexFunction);
} catch(...) {
mexHandleException(callbackErrHandler);
return;
}
}
MEXFUNCTION_LINKAGE
void mexFunctionAdapter(int nlhs_,
int nlhs,
int nrhs,
void* vrhs[],
void* mFun,
void (*callbackOutput)(int, void**),
void (*callbackErrHandler)(const char*, const char*)) {
matlab::mex::Function* mexFunction = reinterpret_cast<matlab::mex::Function*>(mFun);
std::vector<matlab::data::Array> edi_prhs;
edi_prhs.reserve(nrhs);
implToArray(nrhs, vrhs, edi_prhs);
std::vector<matlab::data::Array> edi_plhs(nlhs);
matlab::mex::ArgumentList outputs(edi_plhs.begin(), edi_plhs.end(), nlhs_);
matlab::mex::ArgumentList inputs(edi_prhs.begin(), edi_prhs.end(), nrhs);
try {
(*mexFunction)(outputs, inputs);
} catch(...) {
mexHandleException(callbackErrHandler);
return;
}
arrayToImplOutput(nlhs, edi_plhs, callbackOutput);
}
/*** matlab::mex::Function ***/
matlab::mex::Function::Function() {
functionImpl = mexGetFunctionImpl();
}
matlab::mex::Function::~Function() NOEXCEPT_FALSE {
mexDestroyFunctionImpl(functionImpl);
}
void matlab::mex::Function::operator()(matlab::mex::ArgumentList outs, matlab::mex::ArgumentList ins) {}
std::shared_ptr<matlab::engine::MATLABEngine> matlab::mex::Function::getEngine() {
void* engine = cppmex_getEngine(functionImpl);
return std::make_shared<matlab::engine::MATLABEngine>(engine);
}
void matlab::mex::Function::mexLock() {
int errID = 0;
cppmex_mexLock_with_error_check(functionImpl, &errID);
throwIfError(errID, nullptr);
}
void matlab::mex::Function::mexUnlock() {
int errID = 0;
cppmex_mexUnlock_with_error_check(functionImpl, &errID);
throwIfError(errID, nullptr);
}
std::u16string matlab::mex::Function::getFunctionName() const {
const char16_t* fn = cppmex_getFunctionName(functionImpl);
if(!fn) {
std::string outOfMemoryError = "Not enough memory available to support the request.";
throw matlab::engine::Exception(outOfMemoryError);
}
char16_t* fName = const_cast<char16_t*>(fn);
std::u16string fNameStr = std::u16string(fName);
mexReleaseMemory(nullptr, fName);
return fNameStr;
}
#endif