Expression: string iterators incompatiable, when calling "SetDllDirectory" - c++

I'm receiving following error:
Debug Assertion Failed!
Expression: string iterators incompatible
When trying to run such a code:
std::string string_Dir(){return ".\\Dir\\";}
std::wstring wstring_Dir=std::wstring(
string_Dir().begin()
,string_Dir().end()
);
SetDllDirectory(wstring_Dir.c_str());
Does someone know why
BTW: I followed this.

You are calling string_Dir() twice and then using iterators from different std::string objects to initialize your std::wstring. That is why you are getting an incompatibility error. You must use iterators from the same std::string object, so call string_Dir() once and assign the return value to a variable:
std::string dir = string_Dir();
std::wstring wstring_Dir(dir.begin(), dir.end());
SetDllDirectory(wstring_Dir.c_str());
// or better: SetDllDirectoryW(wstring_Dir.c_str());
That being said, you are not converting from ANSI to UTF-16, so this code will only work correctly if string_Dir() returns a std::string that contains only 7bit ASCII characters. It will fail if the std::string contains any non-ASCII 8bit characters.
There is a simpler solution - you can call SetDllDirectoryA() instead. You don't need the std::wstring, and the OS can do the ANSI-to-UTF16 conversion for you:
SetDllDirectoryA(string_Dir().c_str());

According to the documentation, the value in the function call is supposed to be LPCTSTR instead of LPCTWSTR.

Related

How to convert opcua string to standard string in c++

can someone tell how to convert UaString to std::string in c++.
There is already a question which converts std::string to uastring:
How can i convert a std::string to UaString?
Thanks in advance!
e.g. You have UaString as below:
UaString sString("Test String");
Then you can make standard string as,
std::string myString(sString.toUtf8());
Reference:
UA Server SDK C++
C++ String Class
One way could be to use the toUtf8 member function which returns a const char* that can be used to construct a std::string.
std::string str(uastring.toUtf8());
An alternative if uastring may contain null terminators:
std::string str(uastring.toUtf8(), uastring.size());
Note that UaString::length() shouldn't be used in this case since it returns the number of UTF8 characters while UaString::size() returns the number of bytes (which may be greater).

Can std::string::c_str() be used whenever a string literal is expected?

I would guess that the last two lines in this code should compile.
#include "rapidjson/document.h"
int main(){
using namespace rapidjson ;
using namespace std ;
Document doc ;
Value obj(kObjectType) ;
obj.AddMember("key", "value", doc.GetAllocator()) ; //this compiles fine
obj.AddMember("key", string("value").c_str(), doc.GetAllocator()) ; //this does not compile!
}
My guess would be wrong, though. One line compiles and the other does not.
The AddMember method has several variants as documented here, but beyond that... why is the return of .c_str() not equivalent to a string literal?
My understanding was that where ever a string literal was accepted, you could pass string::c_str() and it should work.
PS: I'm compiling with VC++ 2010.
EDIT:
The lack of #include <string> is not the problem. It's already included by document.h
This is the error:
error C2664: 'rapidjson::GenericValue<Encoding> &rapidjson::GenericValue<Encoding>::AddMember(rapidjson::GenericValue<Encoding> &,rapidjson::GenericValue<Encoding> &,Allocator &)'
: cannot convert parameter 1 from 'const char [4]' to 'rapidjson::GenericValue<Encoding> &'
with
[
Encoding=rapidjson::UTF8<>,
Allocator=rapidjson::MemoryPoolAllocator<>
]
and
[
Encoding=rapidjson::UTF8<>
]
EDIT2:
Please ignore the fact that .c_str() is called on a temporal value. This example is just meant to show the compile error. The actual code uses a string variable.
EDIT3:
Alternate version of the code:
string str("value") ;
obj.AddMember("key", "value", doc.GetAllocator()) ; //compiles
obj.AddMember("key", str, doc.GetAllocator()) ; // does not compile
obj.AddMember("key", str.c_str(), doc.GetAllocator()) ; // does not compile
The std::string::c_str() method returns a char const*. The type of a string literal is char const[N] where N is the number of characters in the string (including the null terminator). Correspondingly, the result of c_str() can not be used in all places where a string literal can be used!
I'd be surprised if the interface you are trying to call requires a char array, though. That is, in your use it should work. It is more likely that you need to include <string>.
even if this code compiled:
obj.AddMember("key2", string("value").c_str(), doc.GetAllocator());
You cannot guarantee that it is safe.
The const char* returned by std::string::c_str() will be valid until the end of this statement.
If the AddMember method stores a copy of the string itself, all well and good. If it stores a pointer then you're doomed. You need knowledge of the inner workings of AddMember before you can reason about the correctness of your code.
I suspect the authors have already thought of this and have constructed overloads that demand that you either send in a std::string object (or equivalent) or a string literal reference (template<std::size_t N> void AddMember(const char (&str)[N]))
Even if this is not what they had in mind, they might be looking to protect you from yourself, in case you inadvertently send in an invalid pointer.
While seemingly an inconvenience, this compile time error indicates a possibly-faulty program. It's a tribute to the library's authors. Because compile time errors are a gazillion times more useful than runtime errors.
Looking at the documentation you linked to, it seems like you are trying to call the overload of AddMember taking two StringRefTypes (and an Allocator). StringRefType is a typedef for GenericStringRef<Ch>, which has two overloaded constructors taking a single argument:
template<SizeType N>
GenericStringRef(const CharType(&str)[N]) RAPIDJSON_NOEXCEPT;
explicit GenericStringRef(const CharType *str);
When you pass a string literal, the type is const char[N], where N is the length of the string + 1 (for the null terminator). This can be implicitly converted to a GenericStringRef<Ch> using the first constructor overload. However, std::string::c_str() returns a const char*, which cannot be converted implicitly to a GenericStringRef<Ch>, because the second constructor overload is declared explicit.
The error message you get from the compiler is caused by it choosing another overload of AddMember which is a closer match.
Re
” why is the return of .c_str() not equivalent to a string literal
A string literal is a zero-terminated string in an array with size known at compile time.
c_str() produces a pointer to (the first item in) a zero-terminated string in an array with size known only at run-time.
Usually a string literal expression will be used in a context where the expression decays to pointer to first item, but in some special cases it does not decays. These cases include
binding to a reference to array,
using the sizeof operator, and
forming a larger literal by compile time concatenation of string literals (simply writing them in order).
I think that's an exhaustive list.
The error message you cite,
” cannot convert parameter 1 from 'const char [4]' to 'rapidjson::GenericValue &
… does not match your presented code
#include "rapidjson/document.h"
int main(){
using namespace rapidjson ;
using namespace std ;
Document doc ;
Value obj(kObjectType) ;
obj.AddMember("key1", "value", doc.GetAllocator()) ; //this compiles fine
obj.AddMember("key2", string("value").c_str(), doc.GetAllocator()) ; //this does not compile!
}
Nowhere in this code is there a three character long string literal.
Hence the claims that “this compiles” and “this does not compile”, are not very trustworthy.
You
should have quoted the actual error message and actual code (at least one of them is not what you had when you compiled), and
should have quoted the documentation of the function you're calling.
Also, note that the actual argument that compiler reacts to in the quoted diagnostic, is a literal or an array declared as such, not a c_str() call.

C++ File Write includes the memory address of the string instead of the contents

All,
I'm still learning C++ but I have an issue in a project I'm tinkering with that I'm curious about. I've noticed that when I try to print the contents of a string that is a member of a class, I get the memory address instead of the contents. I understand that this is because the item is a pointer, but what I"m confused about is that I am using the -> operator to deference it.
Why can I evaluate the class member in an if statement using the -> operator to dereference it but when printing to a file string in the same manner I get the memory address instead?
An example is below:
Lets say I have a class called pClass with a member called m_strEmployeeName. As a side note (I don't know if it matters), the m_strEmployeeName value is CString rather than std::string, so there could be some unknown conversion issue possibly as well.
If I used the following simple code, I get a memory address.
std::ofstream file("testfile.text");
file << pClass->m_strEmployeeName;
file.close();
I get the same behavior with the following dereferencing method (which I would expect since -> is the same thing).
std::ofstream file("testfile.text");
file << (*pClass).m_strEmployeeName;
file.close();
Any idea on what I'm doing wrong?
It is because your CString class is actualy CStringW class wich contain wchar_t strings so std::ofstream not contain operator >> overload that support wchar_t* strings. To print CStringW class objects you may use this type of stream std::wofstream it recognize wchar_t* strings properly and output will be right.
std::wofstream file("testfile.text");
file << pClass->m_strEmployeeName;
file.close();
You may also create your program in multibyte character support. It can be specified in your project settings. But I suggest you to stay with UNICODE.
Try casting CString to a char pointer:
file << (LPCTSTR)pClass->m_strEmployeeName;
see: How to convert CString and ::std::string ::std::wstring to each other?
Note: This will only work if you have TCHAR defined as 8 bits. If you're using 16-bit UNICODE TCHAR, you'd have one more conversion.
Here is one way of doing the TCHAR conversion:
char c_str[1000];
size_t ret;
wcstombs_s(
&ret,
c_str,
sizeof(c_str),
(LPCTSTR)pClass->m_strEmployeeName,
pClass->m_strEmployeeName.GetLength()
);
std::ofstream file("testfile.text");
file << c_str;
file.close();
Useful if you need 8-bit ASCII file but have a UNICODE CString to work with.

C++/CX - I need to pass a Platform::String into a method that takes a const char*?

I'm new to c++ (I'm a c# developer).
I have an SQLite wrapper class that requires you to pass in a database name as a const char* , however I only have it as a Platform::String (after doing a file search).
I cant seem to find a way to convert the Platform::String to const char*.
Ive seen another question on StackOverflow that explain why it isnt straight-forward, but no sample code or end-to-end solution.
Can anyone help me ?
Thanks
Disclaimer: I know little about C++/CX, and I'm basing the answer on the documentation here.
The String class contains 16-bit Unicode characters, so you can't directly get a pointer to 8-bit char-typed characters; you'll need to convert the contents.
If the string is known to only contain ASCII characters, then you can convert it directly:
String s = whatever();
std::string narrow(s.Begin(), s.End());
function_requiring_cstring(narrow.c_str());
Otherwise, the string will need translating, which gets rather hairy. The following might do the right thing, converting the wide characters to multi-byte sequences of narrow characters:
String s = whatever();
std::wstring wide(s.Begin(), s.End());
std::vector<char> buffer(s.Length()+1); // We'll need at least that much
for (;;) {
size_t length = std::wcstombs(buffer.data(), wide.c_str(), buffer.size());
if (length == buffer.size()) {
buffer.resize(buffer.size()*2);
} else {
buffer.resize(length+1);
break;
}
}
function_requiring_cstring(buffer.data());
Alternatively, you may find it easier to ignore Microsoft's ideas about how strings should be handled, and use std::string instead.

CString error, 'CString': is not a member of 'ATL::CStringT<BaseType, StringTraits>'

I am trying to do this:
#include <atlstr.h>
CHAR Filename; // [sp+26Ch] [bp-110h]#1
char v31; // [sp+36Ch] [bp-10h]#1
int v32; // [sp+378h] [bp-4h]#1
GetModuleFileNameA(0, &Filename, 0x100u);
CString::CString(&v31, &Filename);
But I am getting the compiler error C2039:'CString': is not a member of 'ATL::CStringT'
This is a non MFC based dll, but according to the docs you should be able to use CString functionality with the include #include atlstr.h how do I make it work?
Thanks
That's not how constructors are invoked in C++.
CString s = CString(&v21,&File);
Note that GetModuleFilename expects a pointer to an array of characters (which it fills), not a pointer to a single character. Your code is therefore doomed to crash at runtime.
You have several problems in this code snippet:
1) CHAR Filename; declares a variable that is only a single character. However, GetModuleFileNameA expects to be given a pointer to an array of characters. When you pass the parameters &Filename and 0x100u you would make it think that &Filename points to an array of memory with room for up to 256 characters. However, as written in your snipped, it's only a single character. Thus you would have a bad buffer overflow.
Filename should most likely be declared as CHAR Filename[0x100]; in this case. That would also mean you don't need to take the address of Filename when passing it to that function. So the call would then be written as GetModuleFileNameA(0, Filename, 0x100u);
2) When writing code for a constructor, you define is by writing something similar to CString::CString (using whatever your class's name is) and then filling out the function. However, when using a constructor you don't use that syntax at all. You don't call CString::CString() to create a CString object.
You would have to choose an name for the CString object, such as "FilenameStr". So the in the context of you code you would write something like CString FilenameStr(Filename);
3) As implied at the end of the last point, the parameters you are trying to pass to the constructor are wrong. &v31 and &Filename would each by pointers to characters in your original code. However, as far as I know, CString does not have any constructor that takes two character pointers.
I can't even tell how v31 is supposed to be involved there, but it doesn't seem necessary at all. If you want to fill a CString with the contents of a character array, then you can just pass that array to the constructor and it will take care of everything. So, something like CString FilenameStr(Filename);