259 lines
7.9 KiB
C++
259 lines
7.9 KiB
C++
|
/* Copyright 2017 The MathWorks, Inc. */
|
||
|
|
||
|
#ifndef CPPSHARED_LIB_PATH_INIT_HPP
|
||
|
#define CPPSHARED_LIB_PATH_INIT_HPP
|
||
|
|
||
|
#ifdef _WIN32
|
||
|
// Required for path initialization, which we only need to perform on
|
||
|
// Windows.
|
||
|
#include "matlab_runtime_version.hpp"
|
||
|
|
||
|
#define WIN32_LEAN_AND_MEAN
|
||
|
#include <windows.h>
|
||
|
#else
|
||
|
#include <sys/stat.h>
|
||
|
#endif
|
||
|
|
||
|
#include <algorithm>
|
||
|
#include <iostream>
|
||
|
#include <string>
|
||
|
|
||
|
namespace matlab {
|
||
|
namespace cpplib {
|
||
|
namespace detail {
|
||
|
|
||
|
#ifdef _WIN32
|
||
|
|
||
|
// DLL will be found at, e.g., matlab\runtime\win64\libMatlabCppSharedLib9_3.dll.
|
||
|
|
||
|
// Construct filename, unpreceded by path.
|
||
|
inline std::wstring getDllNameExclusiveOfPath()
|
||
|
{
|
||
|
return std::wstring(MATLAB_CPP_SHARED_LIB_BASE_NAME)
|
||
|
+ MATLAB_CPP_SHARED_LIB_SUFFIX;
|
||
|
}
|
||
|
|
||
|
template<typename T, typename Out>
|
||
|
inline void split(const std::basic_string<T> &s, T delim, Out result) {
|
||
|
std::basic_stringstream<T> ss;
|
||
|
ss.str(s);
|
||
|
std::basic_string<T> item;
|
||
|
while (std::getline(ss, item, delim)) {
|
||
|
*(result++) = item;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
inline std::vector<std::wstring> split(const std::basic_string<T> &s, T delim) {
|
||
|
std::vector<std::basic_string<T>> elems;
|
||
|
split(s, delim, std::back_inserter(elems));
|
||
|
return elems;
|
||
|
}
|
||
|
|
||
|
inline std::wstring getValueFromEnvVarW(const std::wstring &varName)
|
||
|
{
|
||
|
DWORD bufferSize = GetEnvironmentVariableW(varName.c_str(), NULL, 0);
|
||
|
if (bufferSize)
|
||
|
{
|
||
|
std::wstring ret(bufferSize, wchar_t(0));
|
||
|
DWORD getPathEnv = GetEnvironmentVariableW(varName.c_str(), &ret[0], bufferSize);
|
||
|
ret.resize(bufferSize-1);
|
||
|
return (getPathEnv ? ret : L"");
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return L"";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline bool setEnvVarW(const std::wstring & varName, const std::wstring & varValue)
|
||
|
{
|
||
|
BOOL ret = SetEnvironmentVariableW(varName.c_str(), varValue.c_str());
|
||
|
if (!ret)
|
||
|
{
|
||
|
DWORD err = GetLastError();
|
||
|
std::cerr << "Attempt to set environment variable '" << std::string(varName.cbegin(), varName.cend()) << "' "
|
||
|
<< "to '" << std::string(varValue.cbegin(), varValue.cend()) << "' failed with error code " << err << std::endl;
|
||
|
}
|
||
|
return ret ? true : false;
|
||
|
}
|
||
|
|
||
|
inline std::wstring getPathFromEnvVarW()
|
||
|
{
|
||
|
return getValueFromEnvVarW(L"PATH");
|
||
|
}
|
||
|
|
||
|
inline std::vector<std::wstring> getPathElementsFromEnvVarW()
|
||
|
{
|
||
|
std::wstring buf = getPathFromEnvVarW();
|
||
|
return split(buf, L';');
|
||
|
}
|
||
|
|
||
|
inline bool fileExistsW(const std::wstring & wstrPath)
|
||
|
{
|
||
|
DWORD dwAttrib = GetFileAttributesW(wstrPath.c_str());
|
||
|
return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
|
||
|
!(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
|
||
|
}
|
||
|
|
||
|
inline bool fileExistsInDirW(const std::wstring & wstrFilename, const std::wstring & wstrDir)
|
||
|
{
|
||
|
if (wstrDir.empty() || wstrFilename.empty())
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
std::wstring wstrPath(wstrDir);
|
||
|
if (wstrPath[wstrPath.length()-1] != L'\\')
|
||
|
{
|
||
|
wstrPath += L"\\";
|
||
|
}
|
||
|
wstrPath += wstrFilename;
|
||
|
return fileExistsW(wstrPath);
|
||
|
}
|
||
|
|
||
|
/// Get the first directory in the specified collection of directories
|
||
|
/// that contains a file with the name specified by wstrFilename.
|
||
|
/// @param wstrFilename file to be found
|
||
|
/// @param wstrDirs directories to search
|
||
|
/// @returns First directory in `wstrDirs` that contains `wstrFilename`. Any
|
||
|
/// trailing backslash will be stripped.
|
||
|
inline std::wstring getFirstDirWhereFileIsFoundW(const std::wstring & wstrFilename,
|
||
|
const std::vector<std::wstring> & wstrDirs)
|
||
|
{
|
||
|
bool bFound = false;
|
||
|
std::wstring pathElementWhereFound;
|
||
|
for (std::wstring wstrDir : wstrDirs)
|
||
|
{
|
||
|
if (fileExistsInDirW(wstrFilename, wstrDir))
|
||
|
{
|
||
|
// chop off trailing backslash, if any
|
||
|
size_t len = wstrDir.length();
|
||
|
if (wstrDir[len-1] == L'\\')
|
||
|
{
|
||
|
wstrDir.resize(len-1);
|
||
|
}
|
||
|
return wstrDir;
|
||
|
}
|
||
|
}
|
||
|
return L"";
|
||
|
}
|
||
|
|
||
|
inline std::wstring getFirstDirOnPathWhereFileIsFoundW(const std::wstring & wstrFilename)
|
||
|
{
|
||
|
std::vector<std::wstring> pathElements = getPathElementsFromEnvVarW();
|
||
|
return getFirstDirWhereFileIsFoundW(wstrFilename, pathElements);
|
||
|
}
|
||
|
|
||
|
inline std::wstring getDirToAddDynamicallyToPathW()
|
||
|
{
|
||
|
std::wstring dir = getFirstDirOnPathWhereFileIsFoundW(getDllNameExclusiveOfPath());
|
||
|
if (!dir.empty())
|
||
|
{
|
||
|
dir += L"\\..\\..\\extern\\bin\\win64";
|
||
|
}
|
||
|
return dir;
|
||
|
}
|
||
|
|
||
|
inline bool loadMatlabDataArrayLibrary()
|
||
|
{
|
||
|
std::wstring wpath = getDirToAddDynamicallyToPathW();
|
||
|
if (wpath.empty())
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
wpath += L'\\';
|
||
|
wpath += L"libMatlabDataArray.dll";
|
||
|
HMODULE hmod = LoadLibraryW(wpath.c_str());
|
||
|
return (hmod ? true : false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class MatlabCppSharedLibraryPathInitializer
|
||
|
{
|
||
|
public:
|
||
|
MatlabCppSharedLibraryPathInitializer()
|
||
|
{
|
||
|
// Ignore return value.
|
||
|
loadMatlabDataArrayLibrary();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
static MatlabCppSharedLibraryPathInitializer pathInitializer;
|
||
|
|
||
|
|
||
|
inline std::u16string getValueFromEnvVar(const std::u16string &varName)
|
||
|
{
|
||
|
std::wstring wstr = getValueFromEnvVarW(std::wstring(varName.cbegin(), varName.cend()));
|
||
|
return std::u16string(wstr.cbegin(), wstr.cend());
|
||
|
}
|
||
|
|
||
|
inline bool setEnvVar(const std::u16string & varName, const std::u16string & varValue)
|
||
|
{
|
||
|
std::wstring wVarName(varName.cbegin(), varName.cend());
|
||
|
std::wstring wVarValue(varValue.cbegin(), varValue.cend());
|
||
|
return setEnvVarW(wVarName, wVarValue);
|
||
|
}
|
||
|
|
||
|
#else // non-Windows code follows
|
||
|
|
||
|
inline bool fileExists(const std::u16string & strPath)
|
||
|
{
|
||
|
struct stat buffer;
|
||
|
return(stat(matlab::execution::convertUTF16StringToUTF8String(strPath.c_str()).c_str(),
|
||
|
& buffer) == 0);
|
||
|
}
|
||
|
|
||
|
inline bool fileExistsInDir(const std::u16string & ustrFilename, const std::u16string & ustrDir)
|
||
|
{
|
||
|
if (ustrDir.empty() || ustrFilename.empty())
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
std::u16string ustrPath(ustrDir);
|
||
|
if (ustrPath[ustrPath.length()-1] != static_cast<char16_t>('/'))
|
||
|
{
|
||
|
ustrPath += static_cast<char16_t>('/');
|
||
|
}
|
||
|
ustrPath += ustrFilename;
|
||
|
return fileExists(ustrPath);
|
||
|
}
|
||
|
|
||
|
inline std::u16string getValueFromEnvVar(const std::u16string &varName)
|
||
|
{
|
||
|
// This is fine because environment variable names are always ASCII.
|
||
|
std::string sVarName(varName.cbegin(), varName.cend());
|
||
|
const char * val = std::getenv(sVarName.c_str());
|
||
|
if ( val == 0 ) {
|
||
|
return std::u16string();
|
||
|
}
|
||
|
else {
|
||
|
return matlab::execution::convertUTF8StringToUTF16String(val);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline bool setEnvVar(const std::u16string & varName, const std::u16string & varValue)
|
||
|
{
|
||
|
// This is fine because environment variable names are always ASCII.
|
||
|
std::string sVarName(varName.cbegin(), varName.cend());
|
||
|
std::string sVarValue = matlab::execution::convertUTF16StringToUTF8String(varValue);
|
||
|
int ret = setenv(sVarName.c_str(), sVarValue.c_str(), /*overwrite=*/ 1);
|
||
|
if (ret == -1)
|
||
|
{
|
||
|
std::cerr << "setEnvVar(" << sVarName << ", " << sVarValue << " failed." << std::endl;
|
||
|
return false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif // platform
|
||
|
|
||
|
}}} // end of nested namespace
|
||
|
|
||
|
#endif // CPPSHARED_LIB_PATH_INIT_HPP
|
||
|
|