-
Reading ASCII Strings into a Unicode Program
I am developing a new app in MFC under VC 2005. Part of the program has to deal with text from files that are used by some old ASCII programs (the programs were created before unicode existed).
Some of these strings are in an INI file. I attempted to read these in using GetPrivateProfileStringA which is supposed to read in the values to char strings which I convert on use to unicode with the A2W macro.
I was successful in doing this from a binary file, but I'm getting weird behavior from the INI file. (In the binary file I parsed it with a custom parser written for this program as it has a unique file format.)
A couple of times I had the INI file read correctly, but then the A2W macro returned NULL when I did the conversion. Most of the time GetPrivateProfileStringA returns odd values. The first string usually had three characters of 0xcd then the ASCII string. Other strings end up having leading NULLs equal to the number of characters read. For example, if it reads the word "Green", the char array will contain:
0x00, 0x00, 0x00, 0x00, 0x00, 'G', 'r', 'e', 'e', 'n', 0x00
upon return and GetPrivateProfileStringA will return 5.
GetPrivateProfileStringW doesn't work. For the first string, it returns three 0xcd bytes followed by the ASCII string with 0x00 padding, but shifted up a byte due to the three 0xcds at the start.
The old ASCII programs make heavy use of GetPrivateProfileString and it doesn't have any problems. It appears that using the ASCII version in a unicode program causes problems. Am I going to have to write a custom parser to get this data out of the INI file? I did some searching and can't find any information on how to read ASCII strings into a unicode program.
I would think this would be a fairly common problem. I must be searching with the wrong terms.
I don't really care when the strings are converted to unicode. I can do it manually after reading them in, or if they can be done at read in time, that's fine too. I just need it to work.
-
Re: Reading ASCII Strings into a Unicode Program
Quote:
Originally Posted by
wdolson
A couple of times I had the INI file read correctly, but then the A2W macro returned NULL when I did the conversion.
Could you show your code with "A2W macro returned NULL"?
Quote:
Originally Posted by
wdolson
Most of the time GetPrivateProfileStringA returns odd values. The first string usually had three characters of 0xcd then the ASCII string.
0xcd in DEbUG build means uninitialized character. What exactly is the string you are reading from .ini file? Is .ini file an ANSI or UNICODE? (Just open it in binary editor and you will see it!)
Quote:
Originally Posted by
wdolson
Other strings end up having leading NULLs equal to the number of characters read. For example, if it reads the word "Green", the char array will contain:
0x00, 0x00, 0x00, 0x00, 0x00, 'G', 'r', 'e', 'e', 'n', 0x00
upon return and GetPrivateProfileStringA will return 5....
Again: what is the exact string in .ini file (how it looks in a binary editor)?
-
Re: Reading ASCII Strings into a Unicode Program
Quote:
Originally Posted by
VictorN
Could you show your code with "A2W macro returned NULL"?
In the document file (the INI file data is read in CMainFrame at program start)
CString filename = A2W(pFrame->m_CfgData.PinNamePath);
The function includes
USES_CONVERSION;
The string that is getting the 0xcd's is a different string from this one. This one has leading 0x00's.
Quote:
0xcd in DEbUG build means uninitialized character. What exactly is the string you are reading from .ini file? Is .ini file an ANSI or UNICODE? (Just open it in binary editor and you will see it!)
The file is ANSII and needs to remain that way because there are programs that use it that are ANSII.
I zero out m_CfgData before I use it, so I don't know where the 0xcds are coming from.
The string from the INI file is:
[MTLAUNCH]
DataPath = E:\C_Proj\Robson\110111USBChanges\DEBUG
Quote:
Again: what is the exact string in .ini file (how it looks in a binary editor)?
My editor won't copy and paste in hex mode (an old version of UltraEdit). It's definitely ASCII though, not a 00 in the entire file.
The code to read the INI is below. The default value path looks fine in the debugger and this is reading in the string, just with leading characters that are garbage. I have a couple of GetPrivateProfileIntA calls too. Those also get the wrong values.
Code:
int charsread;
char path[256];
char iniFile[256];
int len=255;
memset(&m_CfgData,0,sizeof(m_CfgData));
::GetCurrentDirectoryA(len,path);
strncpy_s(iniFile,path,len);
strncat_s(iniFile,"\\",2);
strncat_s(iniFile,MTCFGFILE,len);
charsread = GetPrivateProfileStringA("MTLAUNCH", "DataPath", path, m_CfgData.DataPath, MAXPATH, iniFile);
-
Re: Reading ASCII Strings into a Unicode Program
I found this class which seems to do the job:
http://www.codeproject.com/KB/files/...097&fr=1#xx0xx
I need to do some surgery on my code to fit in the changes, but it gets the ASCII string and converts it to unicode for me, so that's one less step to deal with.
Bill
-
Re: Reading ASCII Strings into a Unicode Program
Quote:
Originally Posted by
wdolson
I zero out m_CfgData before I use it, so I don't know where the 0xcds are coming from.
Code:
memset(&m_CfgData,0,sizeof(m_CfgData));
Please tell us how m_CfgData is declared. This line of code looks wrong. If it's an array, it definitely is wrong. Look at what is highlighted in red -- if it's an array, get rid of the "&".
If it's wrong, you weren't zeroing out the array, you were zeroing out the address of where the array is declared, not the contents of the array.
Regards,
Paul McKenzie
-
Re: Reading ASCII Strings into a Unicode Program
m_CfgData is a struct with several strings and some ints. I've tried defining it a few different ways.
I removed the memset for now. Removing the & from in front of the m_CfgData won't compile. The function wants a pointer to the structure.
I'm using a completely different way to read the INI file now and I'm still getting weird stuff. I tried defining the strings as CStrings, but when I went to use them, if I moused over them, the debugger says <Bad Pointer>. If I expand the + box on the tool tip, it says ATL::CSimpleStringT <wchar_t,0>. I haven't seen that before, but I don't usually mouse over CStrings, they just tend to work most of the time.
I experimented declaring DataPath as a TCHAR array
Code:
typedef struct
{
//CString DataPath;
TCHAR DataPath[MAXPATH];
int DrvType;
int DrvPort;
CString ConfigPath;
CString MapPath;
CString PinNamePath;
CString SocketPath;
CString CalPath;
CString clrBackground;
CString clrGrid;
int MeasureSpec;
int SuperMeasure;
}IniData;
I'm getting very weird behavior. l looked at DataPath in the memory view window and it, of course comes up as all 0xcd. Then I did
m_CfgData.DataPath[0] = 0L;
This set the 4th and 5th bytes in the string to 0. The first three bytes are still 0xcd. It appears for writing purposes, the first entry starts at the 4th byte, but for reading, the first entry starts at the first byte.
I'm seeing this same thing when I try to write a string to the variable. The first three bytes are unchanged, but everything that reads the string sees 0xcd as the first character.
This is completely bizarre. I've been writing C and C++ for over 20 years and have never seen anything like this. I have not worked all that much with multibyte character sets, but I don't think this is working the way it's supposed to.
Bill
-
Re: Reading ASCII Strings into a Unicode Program
Quote:
Originally Posted by
wdolson
m_CfgData is a struct with several strings and some ints. I've tried defining it a few different ways.
I removed the memset for now. Removing the & from in front of the m_CfgData won't compile. The function wants a pointer to the structure.
You cannot call memset() on a structure that is not POD.
Quote:
I'm using a completely different way to read the INI file now and I'm still getting weird stuff. I tried defining the strings as CStrings, but when I went to use them, if I moused over them, the debugger says <Bad Pointer>. If I expand the + box on the tool tip, it says ATL::CSimpleStringT <wchar_t,0>. I haven't seen that before, but I don't usually mouse over CStrings, they just tend to work most of the time.
The problem is simple -- you think that C++ is 'C'.
Your structure contains CStrings -- you cannot use low-level C functions to manipulate or initialize these structures. You must properly construct and initialize these objects. Functions such as memset(), memcpy(), ZeroMemory(), etc. just blindly go through your objects and rips them to shreds. They know nothing about v-tables, destructors, constructors, etc.
In C++, you have two basic types, POD (Plain Old Data) and non-POD. The POD types are compatible with 'C' types. It's the non-POD types that cannot be treated as 'C' types. Example:
Code:
CString s;
memset(s, 0, sizeof(CString));
This code, which is basically what you tried to do, is absolutely no good. That's why you're getting all sorts of weird behaviour -- you're treating C++ types as 'C' types.
Regards,
Paul McKenzie
-
Re: Reading ASCII Strings into a Unicode Program
I tried moving the code to the document, and it loads OK. There is something weird with loading it in the main frame. I found I could get the strings to load if I created a TCHAR string at the top of the struct and set element 0 to 0L, but again it set the 4th and 5th byte, not the 1st two bytes.
Then when I tried to use the strings in the document, by just copying one CString to another, the recipient CString didn't get anything. The = operator did nothing.
It works OK when I put the code in the document, but I can't leave it there. Loading a copy every time the document loads is a waste of space.
Where would be a good place to load this if the main frame won't work?
Bill
-
Re: Reading ASCII Strings into a Unicode Program
Quote:
Originally Posted by
wdolson
I tried moving the code to the document, and it loads OK. There is something weird with loading it in the main frame.
Again, you cannot write code as you claim you wrote and expect correct behaviour.
Quote:
Then when I tried to use the strings in the document, by just copying one CString to another, the recipient CString didn't get anything. The = operator did nothing.
That is because you "ripped it to shreds" by zeroing out the CString's guts calling memset(), memcpy(), what have you.
You completely trashed the internal reference counting system used by CString. The reference counting system of CString is responsible for copying CString's correctly while using a single buffer, and memset() or memcpy() called on CStrings or structs/classes that contains CStrings will make reference counting not work. Once you do that, your program isn't going to work, or it will work erratically.
So it doesn't make any difference what you're trying to do if you're writing code that leads to undefined behaviour.
Regards,
Paul McKenzie
-
Re: Reading ASCII Strings into a Unicode Program
Moving the loading code to the app class works.
I am still wondering why it wouldn't work right in the main frame.
Bill
-
Re: Reading ASCII Strings into a Unicode Program
Quote:
Originally Posted by
wdolson
Moving the loading code to the app class works.
I am still wondering why it wouldn't work right in the main frame.
Bill
And again, if you're writing code that leads to undefined behaviour, there is no guarantee if that code is actually working, or if you're just lucky that it hasn't gone down in flames.
If it's an MFC-based architectural reason why the code doesn't work, that's one story -- but I am not convinced of this, as your previous posts shows that you were doing things incorrectly with respect to handling non-POD types.
Regards,
Paul McKenzie
-
Re: Reading ASCII Strings into a Unicode Program
This is what I'm saying -- let's go back to your post here:
Code:
typedef struct
{
TCHAR DataPath[MAXPATH];
int DrvType;
int DrvPort;
CString ConfigPath;
CString MapPath;
CString PinNamePath;
CString SocketPath;
CString CalPath;
CString clrBackground;
CString clrGrid;
int MeasureSpec;
int SuperMeasure;
}IniData;
OK.
First, there is no need for "typedef struct" in a C++ program. That is a holdover from 'C'. Even though it isn't fatal to do the "typedef struct", it is a sign of things to come that are not good, i.e. 'C' coding done on a C++ type.
Code:
struct IniData
{
TCHAR DataPath[MAXPATH];
int DrvType;
int DrvPort;
CString ConfigPath;
CString MapPath;
CString PinNamePath;
CString SocketPath;
CString CalPath;
CString clrBackground;
CString clrGrid;
int MeasureSpec;
int SuperMeasure;
IniData() : DrvType(0), DrvPort(0), MeasureSpec(0), SuperMeasure(0)
{ memset(DataPath, 0, sizeof(DataPath); }
};
Now, the structure is initialized since it now has a default constructor. You do not use memset() to initialize this structure. Now with the default constructor, all fields have data, and the array is filled with 0 when I do this:
Code:
IniPath iPath; // no memset() -- the object has been initialized using the constructor.
I can use memset() but only on the internal TCHAR array, since the array is a POD type. I could have been more safe by using std::fill, as fill() works on POD and non-POD types:
Code:
#include <algorithm>
//....
struct IniData
{
//...
IniData() : DrvType(0), DrvPort(0), MeasureSpec(0), SuperMeasure(0)
{ std::fill(DataPath, DataPath + MAXPATH, 0); }
};
Copying: When you copy an IniPath to another, you don't use memcpy() or any similar function. Do this instead:
Code:
IniPath iPath;
IniPath iPath2 = iPath;
//or
IniPath iPath3;
iPath = iPath3;
This is what is expected when handling non-POD types such as IniStruct.
Regards,
Paul McKenzie
-
Re: Reading ASCII Strings into a Unicode Program
Thanks for the info. I learned C pretty much formally, but taught myself C++ on the job. There are some gaps in my education.
One thing, I wasn't talking about making a copy of IniPath, just a copy of one of the CStrings in it that was already set with data.
For example,
m_CfgData.PinNamePath is set with data when the INI is read. Then later when that path is used, I do this:
CString filename = pFrame->m_CfgData.PinNamePath;
When the m_CfgData structure is filled within the MainFrame, the above setting of filename results in a NULL string, even though I can look at the string in m_CfgData.PinNamePath and it looks correct.
When I move the code to load data into m_CfgData to the app class, or the document class, setting filename works properly with no problems.
My conclusion is there is something odd about putting this sort of thing in the main frame because it works as expected everywhere else.
I will add the initialization code as you suggest just to be proper and to make sure everything starts in a known state.
Bill
-
Re: Reading ASCII Strings into a Unicode Program
Quote:
Originally Posted by
wdolson
...
When I move the code to load data into m_CfgData to the app class, or the document class, setting filename works properly with no problems.
My conclusion is there is something odd about putting this sort of thing in the main frame because it works as expected everywhere else.
I will add the initialization code as you suggest just to be proper and to make sure everything starts in a known state.
Please, don't do any code movements until your buggy code won't be fixed. Those movements won't help you at all. Never. :cool:
-
Re: Reading ASCII Strings into a Unicode Program
Quote:
Originally Posted by
wdolson
Thanks for the info. I learned C pretty much formally, but taught myself C++ on the job. There are some gaps in my education.
That can be an issue if you learned 'C' first. The problem is that there are things you can do in 'C' that you cannot do in C++, regardless of how safe or "common sense" it may look.
Basically, 'C' has only one basic type -- POD (Plain Old Data). Everything in 'C' is a POD type -- doubles, ints, pointers, arrays, structs, everything. This means you can call 'C' functions to manipulate these types in one shot, functions such as memset(), memcpy(), ZeroMemory(), malloc(), free(), etc. because there is nothing special or hidden behind the scenes about these types.
However for C++, you have a second basic type, and those are simply non-POD types. These types have user-defined constructors, destructors, copy constructors, virtual functions, or derived from a base class, etc. In other words, there is no compatible equivalent in 'C' for these types. CString is one such non-POD type, and any struct or class that has CString automatically becomes non-POD.
This means these entities must be handled especially carefully. No memset(), memcpy(), etc. calls to set the data, no calls to malloc() or calloc() to create these types dynamically, etc. You can only construct these types using classical C++ methods, i.e. construction, using operator new to create them dynamically, using the "=" to assign, and of course, you use the public interface if these types are structs or classes. That's it -- anything else is undefined behaviour.
The CString was a classic example as I stated previously -- there is an internal reference count that the CString class maintains, and wiping out this information with memset() will cause the CString object to not behave properly. Another classic mistake is creating these types with malloc() --, if you were to create a CString with "malloc", you will see the CString is bogus, because it isn't really created. It's just a blob of bytes that does nothing -- as soon as you try to call any member function of CString, you will probably crash.
Quote:
One thing, I wasn't talking about making a copy of IniPath, just a copy of one of the CStrings in it that was already set with data.
For example,
[FONT=monospace]m_CfgData.PinNamePath is set with data when the INI is read. Then later when that path is used, I do this:
CString filename = pFrame->m_CfgData.PinNamePath;
Yes, but as stated, if you've messed up the reference counting aspect of CString, your program might as well crash (unfortunately, these bugs usually don't show up, and you have a program that seems to work but is really faulty).
Quote:
When the m_CfgData structure is filled within the MainFrame, the above setting of filename results in a NULL string, even though I can look at the string in m_CfgData.PinNamePath and it looks correct.
Well, there is no such thing as a NULL CString. A CString can be empty, but never NULL. Also, it could be that your debugger is not showing you the info you need to see, and it isn't the CString itself. The debugger has its own set of rules on how to display various types. So you need to determine if the CString has actually gone off the deep end, or if it's just the way the debugger is showing you the data.
Regards,
Paul McKenzie
-
Re: Reading ASCII Strings into a Unicode Program
Quote:
Originally Posted by
wdolson
When I move the code to load data into m_CfgData to the app class, or the document class, setting filename works properly with no problems.
I will emphasize what VictorN has stated.
If it is determined that the issue is not an MFC architecture related issue (for example, there is an MFC reason why the code doesn't work, and not because of bugs), then you don't move any code.
By moving code, all you did was move the potential bug to another location in your program, and now the bug is probably hidden. Then you deploy the code on a customer's machine, and the code crashes -- that's how these things happen.
I emphasize to never finagle with the code by moving it around if you see a bug. Take the buggy code and fix it. If you do move the code, then the problem gets more difficult, if not impossible to fix.
Regards,
Paul McKenzie
-
Re: Reading ASCII Strings into a Unicode Program
Unless someone can point me to some literature that says otherwise, I'm pretty well convinced this is an MFC architecture issue. I put the exact same code in the mainframe and the app class. They even used the exact same struct definition in the same header file.
The CStrings ended up as <Bad Ptr> after writing to them with code like the following:
TCHAR *pszRet;
pszRet = (TCHAR *)ini.GetValue(_T("MTLAUNCH"), _T("DataPath"), path);
m_CfgData.DataPath = pszRet;
ini.GetValue is from a class I found for getting data to and from INI files and also does the ASCII to Unicode translation.
The above code works without any problems at all in the app class, but in the mainframe, m_CfgData.DataPath says <Bad Ptr> after it is supposed to be set.
The way the structure was originally defined, it was POD. The strings were all char arrays statically defined as MAXPATH in length.
I was wrong in my nomenclature earlier, the CString was at least appearing to be an empty string when I tried to set the new CString to the one stored in the mainframe.
I don't have infinite time to drill down to the lowest levels of the MFC architecture to completely prove this. I am doing this project for someone else and my client is paying the bills. I have experimented doing this a couple of different ways and it worked every time from the app class and failed every time from the mainframe.
That's enough for me to move ahead at this point. I know it isn't perfect, but we don't always have time to do a DNA test to determine if a duck is really a duck.
I am interested to know if this is a known limitation of the MFC architecture, but at this point it is academic.
Bill
-
Re: Reading ASCII Strings into a Unicode Program
Did you remove all the m_CfgData "initializations" with memset?
Did you implement a ctor in your struct IniData?
-
Re: Reading ASCII Strings into a Unicode Program
-
Re: Reading ASCII Strings into a Unicode Program
Could you show your updated code?
Are you still trying to call ANSI functions in your UNICODE applications?
What is the relationships between your updated structure and those ANSI functions calls?
-
Re: Reading ASCII Strings into a Unicode Program
Code:
pszRet = (TCHAR *)ini.GetValue(_T("MTLAUNCH"), _T("DataPath"), path);
I am curious about this TCHAR* cast. What is the actual type returned by GetValue()?
-
Re: Reading ASCII Strings into a Unicode Program
It returns a wchar_t* which as far as I can tell is identical to a TCHAR * in Unicode, but the compiler couldn't deal with it without the cast.
Bill
-
Re: Reading ASCII Strings into a Unicode Program
Quote:
Originally Posted by
wdolson
It returns a wchar_t* which as far as I can tell is identical to a TCHAR * in Unicode, but the compiler couldn't deal with it without the cast.
Bill
It's always a danger sign when you have to cast in order to force the compiler to accept something. Can you provide the exact error message you get without the cast?
-
Re: Reading ASCII Strings into a Unicode Program
Quote:
Originally Posted by
wdolson
It returns a wchar_t* which as far as I can tell is identical to a TCHAR * in Unicode, but the compiler couldn't deal with it without the cast.
It isn't the compiler's fault. You have faulty code, and the compiler is correctly informing you that the two pointer types are not the same, saving you from shooting yourself in the foot.
For example, the compiler can't deal with this either without me casting:
Code:
class Elephant
{
// stuff that makes an elephant an elephant
};
class Doughnut
{
// stuff that makes a doughnut a doughnut
};
Doughnut* GetDoughnut()
{
return new Doughnut;
}
int main()
{
Elephant *e;
e = (Elephant*)GetDoughnut();
}
I casted a pointer to a Doughnut to a pointer to an Elephant. If I remove the cast, the compiler correctly states that the pointers are not the same type. So is a Doughnut an Elephant? Of course not.
Basically, you're letting 'C' creep into a C++ program. You can cast anything to anything using a C-style cast. By doing this, you're telling the compiler to shut-up, and you should not be doing this in a C++ program. If the compiler says "type A isn't the same as type B", believe it and fix the error by not casting, but looking carefully at your code and your design.
Regards,
Paul McKenzie
-
Re: Reading ASCII Strings into a Unicode Program
Quote:
Originally Posted by
Lindley
It's always a danger sign when you have to cast in order to force the compiler to accept something. Can you provide the exact error message you get without the cast?
error C2440: '=' : cannot convert from 'const wchar_t *' to 'TCHAR *'
Bill
-
Re: Reading ASCII Strings into a Unicode Program
Quote:
Originally Posted by
VictorN
Could you show your updated code?
Are you still trying to call ANSI functions in your UNICODE applications?
What is the relationships between your updated structure and those ANSI functions calls?
The class I'm using to read the ini is called CSimpleIni from here http://code.jellycan.com/simpleini/. Using this, I can eliminate the ANSI function calls in the program.
It's usage is pretty simple:
Code:
TCHAR iniFile[MAXPATH];
const TCHAR *pszRet;
// skipping code to set iniFile...
CSimpleIni ini(TRUE, FALSE, FALSE);
SI_Error rc = ini.LoadFile(iniFile);
pszRet = ini.GetValue(_T("MTLAUNCH"), _T("DataPath"), path);
m_CfgData.DataPath = pszRet;
I added the const to the declaration of pszRet after the cast was brought to my attention.
The struct is now declared as:
Code:
struct IniData
{
CString DataPath;
int DrvType;
int DrvPort;
CString ConfigPath;
CString MapPath;
CString PinNamePath;
CString SocketPath;
CString CalPath;
CString clrBackground;
CString clrGrid;
int MeasureSpec;
int SuperMeasure;
IniData() : DrvType(0), DrvPort(0), MeasureSpec(0), SuperMeasure(0) {}
};
Bill
-
Re: Reading ASCII Strings into a Unicode Program
Quote:
Originally Posted by
wdolson
error C2440: '=' : cannot convert from 'const wchar_t *' to 'TCHAR *'
Bill
That error is legitimate. Never ignore it.
What it means is that you're attempting to take a pointer to a const field, and just assuming you can write to it if need be. The compiler can never assume this, and neither should you.
For example:
Code:
int main()
{
const char *p1 = "abc123";
char *p2 = (char *)p1; // I told the compiler to shut up.
p2[0] = 'x'; // oops
}
This is the "foot shooting scenario" that the compiler is trying to prevent.
A const T* is not the same as a T*. The former implies that you cannot write to what T points to, while the latter implies that T points to a writable field.
Regards,
Paul McKenzie
-
Re: Reading ASCII Strings into a Unicode Program
I fixed it after you pointed it out to me.
I'm copying the contents of the pointer right after it's set and then discarding the pointer, so while it was less than optimal coding practice, it wasn't causing the problems I initially wrote about.
Bill
-
Re: Reading ASCII Strings into a Unicode Program
Quote:
Originally Posted by
wdolson
OK. Took a look at the code, and it's supposed to be a generic C++ class for INI reading. The problem is that it has a few issues.
1) Since it's generic, the calls to new[] and then checking for NULL afterwards won't work, unless your code on the outside has overridden operator new[] to return a NULL on failure. This code in particular:
Code:
char * pData = new char[lSize];
if (!pData) {
return SI_NOMEM;
This code isn't going to work if new[] fails, since a failure of new[] throws an exception by default. A return of NULL only happens if you use the nothrow() version of new[] or you (or another entity, i.e. MFC) has overloaded new[] to return a NULL on failure. Since this is a generic class, this code is not correct in this context.
2) The author really should use std::vector<>, and not use new[] /delete[] at all. As it stands now, the code is not exception safe and will produce memory leaks if any of those functions throws an exception. Usage of RAII such as vector<> would fix this issue. Having said this, the class is OK but for these few issues.
Now this code:
Code:
pszRet = ini.GetValue(_T("MTLAUNCH"), _T("DataPath"), path);
m_CfgData.DataPath = pszRet;
Can be shortened to this:
Code:
m_CfgData.DataPath = ini.GetValue(_T("MTLAUNCH"), _T("DataPath"), path);
So what happens in this case? The CString can take a const pointer to a TCHAR to construct itself, so that isn't an issue.
The real fix for your problem is to do this:
Code:
typedef CSimpleIniTempl<TCHAR, SI_NoCase<TCHAR>,SI_ConvertW<TCHAR> > MyCSimpleIni;
Then you use "MyCSimpleIni" or whatever you want to call it in your program. The CSimpleIni is really a typedef for the template instantiation, but it was based on wchar_t.
Therefore just declare a CSimpleIniTempl using the char type you're program is using, and for you , the char type is TCHAR.
This is also a usage of something called "policy-based design", where the type controls how things are done within the template class.
Regards,
Paul McKenzie
-
Re: Reading ASCII Strings into a Unicode Program
Quote:
Originally Posted by
wdolson
I fixed it after you pointed it out to me.
See my last post. The real fix is to declare the CSimpleIniTempl to use TCHAR instead of wchar_t. Then that fixes everything (except for the two issues I pointed out).
Regards,
Paul McKenzie