Packages
evision
1.0.1-rc.0
1.0.1-rc.0
1.0.0
1.0.0-rc.0
0.2.17
0.2.17-rc2
0.2.17-rc1
0.2.16
0.2.16-pre.2
0.2.16-pre
0.2.15
0.2.14
0.2.13
0.2.12
0.2.11
0.2.9
0.2.8
0.2.7
0.2.6
0.2.5
0.2.4
0.2.3
0.2.2
0.2.2-rc2
0.2.1
0.2.0
0.1.39
0.1.38
0.1.37
0.1.36
0.1.35
0.1.34
0.1.33
0.1.32
retired
0.1.31
0.1.30
0.1.29
0.1.28
0.1.27
0.1.26
0.1.26-rc3
0.1.26-rc2
0.1.26-rc1
0.1.26-rc0
0.1.25
0.1.24
0.1.23
0.1.22
0.1.21
0.1.20
0.1.19
0.1.18
0.1.17
0.1.16
0.1.15
0.1.14
0.1.13
0.1.12
0.1.11
0.1.10
0.1.9
0.1.8
0.1.7
OpenCV-Erlang/Elixir binding.
Current section
Files
Jump to
Current section
Files
c_src/windows_fix/windows_fix.cpp
#include <string>
#include <cstring>
#include <stdlib.h>
#include <sstream>
#include <vector>
#include <stdio.h>
#include <windows.h>
#include <libloaderapi.h>
#include <winbase.h>
#include <wchar.h>
#include <erl_nif.h>
ERL_NIF_TERM atom(ErlNifEnv *env, const char *msg) {
ERL_NIF_TERM a;
if (enif_make_existing_atom(env, msg, &a, ERL_NIF_LATIN1)) {
return a;
} else {
return enif_make_atom(env, msg);
}
}
ERL_NIF_TERM error(ErlNifEnv *env, const char *msg) {
ERL_NIF_TERM error_atom = atom(env, "error");
ERL_NIF_TERM msg_term = enif_make_string(env, msg, ERL_NIF_LATIN1);
return enif_make_tuple2(env, error_atom, msg_term);
}
ERL_NIF_TERM ok(ErlNifEnv *env) {
return atom(env, "ok");
}
int evision_windows_fix_dir_exists(LPCWSTR path) {
DWORD dwAttrib = GetFileAttributesW(path);
return (dwAttrib != INVALID_FILE_ATTRIBUTES && (dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}
static ERL_NIF_TERM evision_windows_fix_run_once(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) {
static bool opencv_path_updated = false;
static bool cuda_path_updated = false;
if (opencv_path_updated && cuda_path_updated) return ok(env);
char err_msg[128] = { '\0' };
SYSTEM_INFO systemInfo;
GetNativeSystemInfo(&systemInfo);
std::wstring cpu_arch;
if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) {
cpu_arch = L"x64";
} else if (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ARM64) {
cpu_arch = L"ARM64";
} else {
snprintf(err_msg, sizeof(err_msg) - 1, "Cannot determine current processor architecture: %d", systemInfo.wProcessorArchitecture);
return error(env, err_msg);
}
if (!opencv_path_updated) {
std::wstring directory;
wchar_t path[65536];
HMODULE hm = NULL;
if (GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCWSTR)&evision_windows_fix_run_once, &hm) == 0) {
int ret = GetLastError();
snprintf(err_msg, sizeof(err_msg) - 1, "GetModuleHandle failed, error = %d", ret);
return error(env, err_msg);
}
if (GetModuleFileNameW(hm, (LPWSTR)path, sizeof(path)) == 0) {
int ret = GetLastError();
snprintf(err_msg, sizeof(err_msg) - 1, "GetModuleFileName failed, error = %d", ret);
return error(env, err_msg);
}
directory = path;
wchar_t backslash = '\\';
auto pos = directory.find_last_of(backslash);
auto priv_dir = directory.substr(0, pos);
std::wstring lib_dir;
// test from vc10 to vc99
// this should last for a while
if (sizeof(void*) == 8) {
for (int vc_version = 10; vc_version < 99; vc_version++) {
std::wstringstream t;
t << priv_dir << L"\\" << cpu_arch << L"\\vc";
t << vc_version;
t << L"\\bin";
auto probe = t.str();
if (evision_windows_fix_dir_exists((LPCWSTR)probe.c_str())) {
lib_dir = probe;
break;
}
}
}
else if (sizeof(void*) == 4) {
for (int vc_version = 10; vc_version < 99; vc_version++) {
std::wstringstream t;
t << priv_dir + L"\\x32\\vc";
t << vc_version;
t << L"\\bin";
auto probe = t.str();
if (evision_windows_fix_dir_exists((LPCWSTR)probe.c_str())) {
lib_dir = probe;
break;
}
}
}
if (lib_dir.length() == 0) {
ERL_NIF_TERM ret_term = error(env, "Cannot detect OpenCV lib directory");
return ret_term;
}
printf("Found OpenCV Lib Directory: %ls\r\n", lib_dir.c_str());
PCWSTR opencvLibDirectoryPCWSTR = lib_dir.c_str();
WCHAR pathBuffer[65536];
DWORD pathLen = GetEnvironmentVariableW(L"PATH", pathBuffer, 65536);
WCHAR newPath[65536];
newPath[0] = L'\0';
wcscpy_s(newPath, _countof(newPath), (const wchar_t*)pathBuffer);
wcscat_s(newPath, _countof(newPath), (const wchar_t*)L";");
wcscat_s(newPath, _countof(newPath), (const wchar_t*)opencvLibDirectoryPCWSTR);
SetEnvironmentVariableW(L"PATH", newPath);
SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_USER_DIRS);
DLL_DIRECTORY_COOKIE ret = AddDllDirectory(opencvLibDirectoryPCWSTR);
if (ret == 0) {
DWORD last_error = GetLastError();
LPTSTR error_text = nullptr;
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, HRESULT_FROM_WIN32(last_error), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&error_text, 0, NULL);
if (error_text != nullptr) {
ERL_NIF_TERM ret_term = error(env, error_text);
LocalFree(error_text);
return ret_term;
} else {
ERL_NIF_TERM ret_term = error(env, "error happened when adding OpenCV runtime DLL path, but cannot get formatted error message");
return ret_term;
}
}
opencv_path_updated = true;
}
if (!cuda_path_updated) {
WCHAR CUDARuntimeDIRBuffer[65536];
memset(CUDARuntimeDIRBuffer, 0, sizeof(CUDARuntimeDIRBuffer));
DWORD cudaLen = GetEnvironmentVariableW(L"EVISION_CUDA_RUNTIME_DIR", CUDARuntimeDIRBuffer, 65536);
if (cudaLen > 0) {
WCHAR pathBuffer[65536];
DWORD pathLen = GetEnvironmentVariableW(L"PATH", pathBuffer, 65536);
WCHAR newPath[65536];
newPath[0] = L'\0';
wcscpy_s(newPath, _countof(newPath), (const wchar_t*)pathBuffer);
wcscat_s(newPath, _countof(newPath), (const wchar_t*)L";");
wcscat_s(newPath, _countof(newPath), (const wchar_t*)CUDARuntimeDIRBuffer);
SetEnvironmentVariableW(L"PATH", newPath);
SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_USER_DIRS);
DLL_DIRECTORY_COOKIE ret = AddDllDirectory(CUDARuntimeDIRBuffer);
if (ret == 0) {
DWORD last_error = GetLastError();
LPTSTR error_text = nullptr;
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, HRESULT_FROM_WIN32(last_error), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&error_text, 0, NULL);
if (error_text != nullptr) {
ERL_NIF_TERM ret_term = error(env, error_text);
LocalFree(error_text);
return ret_term;
} else {
ERL_NIF_TERM ret_term = error(env, "error happened when adding CUDA runtime DLL path, but cannot get formatted error message");
return ret_term;
}
}
} else {
#ifdef EVISION_ENABLE_CUDA
printf("Evision is compiled with CUDA support, but CUDA runtime directory is not set.\r\nPlease set EVISION_CUDA_RUNTIME_DIR environment variable to the directory containing CUDA runtime DLLs.\r\n\r\n");
printf(" If you're using cmd.exe, the command should be something like:\r\n\r\n");
printf(" set EVISION_CUDA_RUNTIME_DIR=C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v12.1\\bin\r\n\r\n");
printf(" Please replace the path with the actual path to CUDA runtime DLLs on your system.\r\n");
printf(" Also, please DO NOT QUOTE even if there are spaces in the path.\r\n\r\n");
printf(" If you're using PowerShell, the command should be something like:\r\n\r\n");
printf(" $Env:EVISION_CUDA_RUNTIME_DIR=\"C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v12.1\\bin\"\r\n\r\n");
printf(" Please replace the path with the actual path to CUDA runtime DLLs on your system.\r\n");
printf(" However, please DO ADD QUOTE if there are spaces in the path.\r\n\r\n");
#endif
}
cuda_path_updated = true;
}
return ok(env);
}
static int on_load(ErlNifEnv *,void **,ERL_NIF_TERM) {
return 0;
}
static int on_upgrade(ErlNifEnv*, void**, void**, ERL_NIF_TERM) {
return 0;
}
static ErlNifFunc nif_functions[] = {
{"run_once", 0, evision_windows_fix_run_once, 0},
};
ERL_NIF_INIT(evision_windows_fix, nif_functions, on_load, NULL, on_upgrade, NULL);