class Widget
{
Widget(std::string name);
~Widget();
};
extern "C" int _stdcall DoWidget(TCHAR * Name)
{
std::string newName;
//(***) how do i set newName to Name so I can pass the data
correctly below?
Widget * pWid = new Widget(newName);
//do stuff with the widget
return 1;
}
I am calling DoWidget() from within MSVC++6.0:
CString Ralf = _T("Ralf");
TCHAR WidName[100];
wcscpy(WidName, Ralf);
int Result = DoWidget(WidName);
> class Widget
> {
> Widget(std::string name);
[...]
> extern "C" int _stdcall DoWidget(TCHAR * Name)
> {
> std::string newName;
> //(***) how do i set newName to Name so I can pass the data
> correctly below?
Just do:
// Convert from TCHAR* Name to an ANSI string
CT2A ansiName( Name );
// Assign to std::string
std::string newName = ansiName;
Giovanni
> extern "C" int _stdcall DoWidget(TCHAR * Name)
> {
> std::string newName;
Some more notes:
It seems to me that you are not modifying the Name string in DoWidget
function, so why don't you pass the string parameter using proper
const-correctness?
e.g.
extern "C" int __stdcall DoWidget( const TCHAR * Name );
So, in this way you can simplify also the calling code (considering that
CString has an implicit TCHAR conversion operator):
Instead of your code:
> CString Ralf = _T("Ralf");
> TCHAR WidName[100];
> wcscpy(WidName, Ralf);
> int Result = DoWidget(WidName);
Just do:
CString Ralf = ...
int Result = DoWidget(Ralf);
CString::operator LPCTSTR (i.e. const TCHAR*) will be called.
Of course, we are assuming that you are compiling both the DLL and the
EXE with the same TCHAR setting (e.g. both Unicode, or both ANSI).
Giovanni
Perfect, thanks.
This is great, I did not know this.
Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm
> Note that you are passing in a TCHAR, but you are storing it in a std::string (8-bit
> character string). The problem here is that if your app really is Unicode, you have an
> information-losing transformation. You should use Unicode consistently, and std::string
> doesn't support this. Is there some reason you are using std::string here, where CString
> would have been a better choice?
Joe: you have a good point.
However, I think that the OP can use std::string to store Unicode in a
non-losing way, just using UTF-8 (instead of UTF-16).
Giovanni
> However, I think that the OP can use std::string to store Unicode in a
> non-losing way, just using UTF-8 (instead of UTF-16).
BTW: in case that conversion would be useful to the OP, here is some
code I wrote for that purpose (it is based on ATL and STL std::string
and std::vector classes, so can be used also in Win32 non-MFC projects):
<code>
#include <vector>
#include <string>
//----------------------------------------------------------------------------
// NAME: ConvertUTF16ToUTF8
// DESC: Converts Unicode UTF-16 (Windows default) text to Unicode UTF-8
//----------------------------------------------------------------------------
std::string ConvertUTF16ToUTF8( IN const wchar_t * utf16 )
{
//
// Check input pointer
//
ATLASSERT( utf16 != NULL );
if ( utf16 == NULL )
AtlThrow( E_POINTER );
//
// Handle special case of empty string
//
if ( *utf16 == L'\0' )
{
return "";
}
//
// Consider wchar_t's count corresponding to total string length,
// including end-of-string (L'\0') character.
//
const int utf16Length = wcslen( utf16 ) + 1;
//
// Get size of destination UTF-8 buffer, in chars (= bytes)
//
int utf8Size = ::WideCharToMultiByte(
CP_UTF8, // convert to UTF-8
0, // default flags
utf16, // source UTF-16 string
utf16Length, // total source string length, in wchar_t's,
// including end-of-string \0
NULL, // unused - no conversion required in this step
0, // request buffer size
NULL, NULL // unused
);
ATLASSERT( utf8Size != 0 );
if ( utf8Size == 0 )
{
AtlThrowLastWin32();
}
//
// Allocate destination buffer for UTF-8 string
//
std::vector< char > utf8Buffer( utf8Size );
//
// Do the conversion from UTF-16 to UTF-8
//
int result = ::WideCharToMultiByte(
CP_UTF8, // convert to UTF-8
0, // default flags
utf16, // source UTF-16 string
utf16Length, // total source string length, in wchar_t's,
// including end-of-string \0
&utf8Buffer[0], // destination buffer
utf8Size, // destination buffer size, in bytes
NULL, NULL // unused
);
ATLASSERT( result != 0 );
if ( result == 0 )
{
AtlThrowLastWin32();
}
//
// Build UTF-8 string from conversion buffer
//
return std::string( &utf8Buffer[0] );
}
</code>
In case there is a need to convert from a Unicode UTF-16 CString (in
Unicode build, or when explicit CStringW is used) to Unicode UTF-8 and
store the result in std::string, this code should work:
// Unicode build or use CStringW
CString str;
... assing str...
// Convert from UTF-16 'str' to UTF-8
// (non-losing conversion)
std::string utf8String = ConvertUTF16ToUTF8( str );
HTH,
Giovanni
In general, I fail to see the fascination with std::string in MFC programs. OTOH, in the
few C++ programs I've written without MFC, where I didn't need Unicode, I've used it.
joe
Hi Joe,
The reason it is std::string is the Widget constructor was not written
by a 3rd party and I cannot get it changed. In the other functions
(except the constructor) they use std::wstring.
Thanks,
Hamish
Yes this is the case.
****
Does this not suggest that the Widget constructor is defective? If you have the source,
it should be repaired; otherwise it should be noted as a bug to the vendor.
I've seen this before: someone carefully designs a class, and someone else retrofits an
interface without actually understanding the problem.
joe
*****
>
>Thanks,
>Hamish
My mind is still in vacation: what is OP in this instance?
--
Mihai Nita [Microsoft MVP, Visual C++]
http://www.mihai-nita.net
------------------------------------------
Replace _year_ with _ to get the real email
The OP in this instance is 'hamishd' .
:-)
Giovanni
> Nice example.
Thanks, Joe.
> I would have led to UTF-8 eventually, but I find that most people who use
> std::string use it for completely gratuitous reasons, since there is almost no reason to
> not use CString.
Yes, I agree with you that CString[A/W] plays well with MFC.
Probably the worst part of CString is the implicit operator LPCTSTR,
that makes things like this possible:
CString s;
...
delete s;
I think that it compiles fine (thanks to implicit operator LPCTSTR), but
it causes a run-time crash.
On the other hand, CString has helpful methods like those to trim spaces
right and left, etc. These methods are not available in std::string
interface; however, some clever man added that to the "raw" STL
implementation:
http://www.codeproject.com/KB/stl/STL_string_util.aspx
Giovanni
It is possible to do what you mention here, but I'm not sure why anyone
would want to try to do that since the only time you should ever do a delete
is if you did a new first. I'm not sure this is a huge hole. Also, even it
would compile, as you say, it would most certainly crash and be pretty easy
to trace down in debugging. CString has so many benefits over other string
classes (imo) that it is worth living with the small inconveniences.
Tom
"Giovanni Dicanio" <giovanniD...@REMOVEMEgmail.com> wrote in message
news:O5STEIX...@TK2MSFTNGP02.phx.gbl...
> It is possible to do what you mention here, but I'm not sure why anyone
> would want to try to do that since the only time you should ever do a
> delete is if you did a new first. I'm not sure this is a huge hole.
Of course no one would do that on purpose, but it may happen in some
complex code, and the compiler won't complain (and in general, I prefer
having compiler's complains at compile-time, than run-time bugs :)
However, I think that this is the usual dispute about implicit vs.
explicit conversion operators.
Seems like in modern C++ there is a trend toward using explicit
conversion and not implicit one, e.g. std::string has an explicit
.c_str() method to get access to underlying C-style string buffer.
Seems like modern CString (probably since VC7.1) has a GetString()
method too, similar to STL std::string::c_str() method.
However, at the bottom line, I think that CString interface is more
convenient to use than std::string, like I already wrote elsewhere.
G
Tom
"Giovanni Dicanio" <giovanniD...@REMOVEMEgmail.com> wrote in message
news:eZuO9nac...@TK2MSFTNGP03.phx.gbl...