diff options
| author | Joaquim <jluis@ualg.pt> | 2019-12-01 16:08:03 +0000 |
|---|---|---|
| committer | Even Rouault <even.rouault@spatialys.com> | 2019-12-01 17:08:03 +0100 |
| commit | c3aa3fe4e9ba17737bb013ed6e7a647fdd5303fe (patch) | |
| tree | c88961d946456b8ab712f642c535c4b799d8171f /src/open_lib.cpp | |
| parent | 4d40332fa4fa87509bdc4aee51396f6f05cca113 (diff) | |
| download | PROJ-c3aa3fe4e9ba17737bb013ed6e7a647fdd5303fe.tar.gz PROJ-c3aa3fe4e9ba17737bb013ed6e7a647fdd5303fe.zip | |
Enhance PROJ resource file lookup on Windows for bin\..\share\proj (#1755)
This PR is Windows only. It adds the directory ``.....\bin\..\share\proj``, where ``....\bin`` is the directory hosting ``proj.dll``, to the list of places where ``proj.db`` is searched. In addition to what happens at build time, this PR ads also the ability to do that at run-time. This means that a structure like
....\bin\proj.exe, proj.dll, ...
....\share\proj\proj.db, ...
will still find proj.db without needing to set the PROJ_LIB environment variable
Diffstat (limited to 'src/open_lib.cpp')
| -rw-r--r-- | src/open_lib.cpp | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/src/open_lib.cpp b/src/open_lib.cpp index 7fedb28b..24c31033 100644 --- a/src/open_lib.cpp +++ b/src/open_lib.cpp @@ -151,6 +151,51 @@ void pj_set_searchpath ( int count, const char **path ) proj_context_set_search_paths( nullptr, count, const_cast<const char* const*>(path) ); } +#ifdef _WIN32 +#include <windows.h> +#include <sys/stat.h> +static const char *get_path_from_win32_projlib(const char *name, std::string& out) { + /* Check if proj.db lieves in a share/proj dir parallel to bin/proj.dll */ + /* Based in https://stackoverflow.com/questions/9112893/how-to-get-path-to-executable-in-c-running-on-windows */ + + DWORD path_size = 1024; + + for (;;) { + out.resize(path_size); + memset(&out[0], 0, path_size); + DWORD result = GetModuleFileNameA(nullptr, &out[0], path_size - 1); + DWORD last_error = GetLastError(); + + if (result == 0) { + return nullptr; + } + else if (result == path_size - 1) { + if (ERROR_INSUFFICIENT_BUFFER != last_error) { + return nullptr; + } + path_size = path_size * 2; + } + else { + break; + } + } + // Now remove the program's name. It was (example) "C:\programs\gmt6\bin\gdal_translate.exe" + size_t k = strlen(out.c_str()); + while (k > 0 && out[--k] != '\\') {} + out.resize(k); + + out += "/../share/proj/"; + out += name; + + struct stat fileInfo; + if (stat(out.c_str(), &fileInfo) == 0) // Check if file exists (probably there are simpler ways) + return out.c_str(); + else { + return nullptr; + } +} +#endif + /************************************************************************/ /* pj_open_lib_ex() */ /************************************************************************/ @@ -229,6 +274,10 @@ pj_open_lib_ex(projCtx ctx, const char *name, const char *mode, if( fid ) break; } +#ifdef _WIN32 + /* check if it lives in a ../share/proj dir of the proj dll */ + } else if ((sysname = get_path_from_win32_projlib(name, fname)) != nullptr) { +#endif /* or hardcoded path */ } else if ((sysname = proj_lib_name) != nullptr) { fname = sysname; |
