On Windows I'm trying to use one of the variants of LoadLibrary()
to open a dll
previously written to an std::filesystem::path
with an ofstream
.
Note: I know the dll is written correctly as I can use it in the standard fashion by linking to it at runtime.
I've been trying to combine the methods from the two answers below.
How to convert std::string to LPCSTR?
how to convert filesystem path to string
This seems like it should be pretty basic but with anything I've tried so far I either get an error about conversion to LPCSTR or something like C2228: left of '.c_str' must have class/struct/union
which I am baffled by.
Here's a simple example:
// Assuming I have
// std::filesystem::path path1
// correctly set, I should be able to directly access it in
// a number of ways; i.e. path1.c_str(), path1.string.c_str(), etc.
// in order to pass it the function or a temp variable.
// However direct use of it in LoadLibrary() fails with the C2228 error.
HINSTANCE hGetProcIDDLL = LoadLibrary(path1.c_str());
I've tried avoiding the macro and calling LoadLibraryA()
directly with no luck.
I've also tried various ways of passing path1
with path1.string()
, path1.string.c_str()
, path1.wstring(), etc. with no luck.
I've also tried using a temp variable in a number of ways to avoid the cast within LoadLibrary()
.
LPCSTR temp_lpcstr = path1.c_str(); // Also tried things like path1.string() path1.string.c_str()
// Also tried just using a temp string...
std::string temp_string = path1.string(); // and variants.
I'm willing to try playing with the encoding (like path1.u8string()
etc.) but I think it shouldn't be necessary with use of LoadLibraryA()
directly.
I'm trying to avoid C casts and would prefer a c++ static_ or dynamic_ but I'll use anything that works.
Any help is appreciated.
Thanks in advance.
UPDATE
@eryk-sun's comment and @Gulrak's answer solved it for me.
It looks like with my setup, path1.c_str()
alone is wchar_t
but the LoadLibrary() macro was not picking that up and directing it to LoadLibraryW() as it should.
Note: For anyone else who might stumble onto this in the future here's more details of my specific setup. I'm using the MSVC compiler from 16.1.0 (~VS2019) but that's getting called from VSCode and CMake. I'm not explicitly defining _UNICODE however VSCode's intellisense certainly thinks it's been defined somewhere and points me to LoadLibraryA(). However, I think the compiler is not actually seeing that define so it interprets path1.c_str()
as a wchar_t
.
Actually on Windows you should be able to use LoadLibraryW(path1.c_str())
as on Windows the returned type of std::filesystem::path::c_str() should be a const wchar_t*
so it's a good fit for the LoadLibraryW
expected LPCWSTR
.
As for the error of C2228
my guess is, you tried path1.string.c_str()
as given by your comment, wich should have been path1.string().c_str()
. That would give you a LPCSTR
compatible string for LoadLibaryA
, but if there is a chance of Non-ASCII in your path I would suggest using the explicit LoadLibaryW
version.
In any way: When interfacing WinAPI with std::filesystem::path
you should use the explicit A/W-Version to make your code safe independent of the state of _UNICODE
, and I allways suggest the *W
versions.