Replacing CString in mingw compiler for eclipse - c++

I have some code which is relatively big, but there is one part of it which uses something called CString (http://msdn.microsoft.com/en-us/library/aa300688%28v=vs.60%29.aspx) . Right now I am using the mingw compiler on eclipse and it doesnt seem to recognize it which makes sense. But I need to use the other part of the code. I know I can replace the CString with a const char * but there are several function like append which the code uses which are not defined. I was wondering whats the best way to port this code? Also there are other stdafx.h dependencies also like _T(). Whats the best approach I should take now?

There is a CString replacement over on CodeProject. I just googled for "CString alternative". I haven't looked at it but it should be easier to use that instead of std::string.

Related

How can I convert an std::filesystem::path to LPCSTR for use in one of the LoadLibrary() variants?

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.
You should use string member function of path class which returns std::string. Then call c_stron the returned string.
std::filesystem::path path /* = initialization here */;
std::string str = path.string();
/* some handle = */ LoadLibrary(str.c_str());

movefile() fails error 2 or 123

I'm updating a c++ routine to move files that was written in visual studio express 2008/2010. I'm now running VS Express 2012
Obviously there are changes to the compiler because string functions have to be upgraded to strcpy_s etc. No problem. This is a console app. I never extended my C++ knowledge past C++ to C# etc. as I need little more than to be able to write small utils to do things on the command line. Still I'm able to write somewhat complex utilities.
My issue is movefile() function always fails to move with either error 2 or 123. I'm working in C:\users\alan\downloads folder so I know I have permission. I know the file is there. Small snippet of code is:
char source=".\\test.txt"; // edited for clarity.
char dest=".\\test.txt1";
printf("\nMove\n %s\n to %s\n",source,dest); // just to see what is going on
MoveFile((LPCWSTR) source, (LPCWSTR) dest);
printf("Error %u\n",GetLastError());
output is :
Move
.\test.txt
to .\test.txt1
Error 2
All of my strings are simple char strings and I'm not exactly sure, even after reading, what LPCWSTR was type def'd for and if this is the culprit. So to get this to compile I simply typedef'd my strings. And it compiles. But still it won't move the files.
The code is more complex in developing the source & dest variables but I've reduce it to a simple "just append a 1 to the file name" situation to see if I can just simply rename it. I thought C:\xxx\yyy\zzz\test.txt was maybe wrong in some fashion but that idea fell though with the above test. I've done it with and without the .\ same issue. I'm running out of ideas other than making my own fileopen read/write binary function to replace movefile(). I'm really against that but if I have to I will.
EDIT: I pasted the printf from original code that used FullPathName, I've corrected the snippet.
The fact that you are casting your arguments to LPCWSTR suggests that you are compiling your program with UNICODE defined, which means you are calling MoveFileW and the compiler warned about an argument type mismatch.
Inserting a cast does not fix that. You are telling the compiler to stop complaining, but you haven't actually fixed the problem (the underlying data is still wrong).
Actual solutions:
Use WCHAR as MoveFileW expects (or TCHAR/LPTSTR and the _T macro).
Explicitly call MoveFileA
Compile without UNICODE defined.
Thanks Andrew Medico. I used MoveFileA and the program seems to work now.
I'm not sure I turned off unicode, but I did change one item in the properties.
I'll need to read up on the compiler about unicode/ansi settings. But for now the issue is fixed and I'm sure I've got the idea of what I need to do. "research"!!!!

convert system string to char to be passed to _mkdir function

I am getting a text value from text box and need to pass this to a _mkdir function which takes char*.
So I have:
_mkdir(this->txt_path->Text);
How do I convert this, I am using VS 2008 C++ and have .Net env.
I have looked at other online material which hasn't helped :(
Thanks,
Bruce
Well, like most C API's this one is probably not const correct. You could try to pass in Text.c_str() and see what happens.
If it really does need to modify the string though then first of all, find another function to use, this is a very unsafe one. Second of all, you can use it by doing this:
std::vector<char> buf(Text.begin(), Text.end());
buf.push_back(0);
_mkdir(&buf[0]);

#define Glib::string std:wstring

I have Linux code and I want to port it to Windows. The code uses Glib::ustring, but I want to replace all the strings to std::wstring for testing purposes.
Is there a way to define all Glib::string to std::wstring without changing it in code? Something similar to typedef or #define?
What makes you think that Glib::ustring is interchangeable/interoperable with std::wstring? Most likely if you made that substitution you'd just get a bunch of compiler errors, or if you're unlucky it would compile and run with different semantics.
I think you're going to have to bite the bullet and convert your Linux code to use wstring first and then the Windows port should be a lot less complicated.
That said, assuming you don't need Glib in the Windows version you could remove all references to that and then create your own fake type in a header:
namespace Glib
{
typedef std::wstring ustring;
}

pwsz string confusion

I have never posted before so I am sorry if I am not clear. I am trying to use a third party DLL written in c++ on 2005 and all I have is some very poor documentation. I am dynamically linking to the DLL and using the Ordinal value read from Dependency walker to get a pointer to a method in the DLL. Such as (LPFNDDLLZC) GetProcAddress(hHILCdll, (LPCSTR)15);
My code is written in C++ compiled in Microsoft VS 6.0, I can not turn on the UNICODE defines or I will break existing code.
The documentation for the DLL says all string arguments are pwsz which I believe means pointer to a wide char string null terminated.
I have tried passing in a pointer to an unsigned short, BSTR and various other things and the DLL crashes on the string. I am totally lost as to why, I believe it has to do with my pwsz string construction and I'm lost as to how to fix this. I have read so may articles related but nothing works.
Can anyone help? I can post code if need be.
Thanks.
You could use MultiByteToWideChar to turn your LPSTR into an LPWSTR which should solve your problem.
Thanks to everyone. I did finally get a copy of the DLL source and my problem wasn't my string construction it was the poor documentation. Turns out they are using double pointers, fixes a ton of things!