5

I have this problem in MSVC2008 MFC. I´m using unicode. I have a function prototype:

MyFunction(const char *)

and I'm calling it:

MyfunFunction(LPCTSTR wChar). 

error:Cannot Convert Parameter 1 From 'LPCTSTR' to 'const char *'

How to resolve it?

GSerg
  • 76,472
  • 17
  • 159
  • 346
Annie
  • 149
  • 2
  • 2
  • 6

5 Answers5

5

Since you're using MFC, you can easily let CString do an automatic conversion from char to TCHAR:

MyFunction(CString(wChar));

This works whether your original string is char or wchar_t based.

Edit: It seems my original answer was opposite of what you asked for. Easily fixed:

MyFunction(CStringA(wChar));

CStringA is a version of CString that specifically contains char characters, not TCHAR. There's also a CStringW which holds wchar_t.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
2

LPCTSTR is a pointer to const TCHAR and TCHAR is WCHAR and WCHAR is most probably wchar_t. Make your function take const wchar_t* if you can, or manually create a const char* buffer, copy the contents, and pass that.

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • 2
    Even better, provide a generic translation function from `const wchar_t *` to `const char *` (or `std::wstring` to `std::string`) using locale-aware `wcstombs` and factor all your calls through that. – Kerrek SB Jul 05 '11 at 19:47
  • wcstombs is for :Convert const wchar_t * to char *. I have to convert from LPCTSTR(const wchar_t*) to const char*. – Annie Jul 05 '11 at 19:54
  • @Annie: `wcstombs` will work just fine. Any function that accepts a `const char *` will accept a `char *` too, it'll just treat the latter as if it were `const`. – Praetorian Jul 05 '11 at 19:58
  • @Annie: and where is the problem? If the function accepts a `const char *` it will accept without problems a `char *`. – Matteo Italia Jul 05 '11 at 19:58
  • Matteo: My problem is how to convert const wide char pointer to const single byte char pointer – Annie Jul 05 '11 at 20:12
  • @Annie: Make _two_ "conversion" functions, one serious one from `const wchar_t *`, and one dummy one taking a `const char *` returning immediately. With those two overloads, you can call your conversion function on a `TCHAR` no matter how that ends up being typedef'ed (it'll be either `char` or `wchar_t`.) – Kerrek SB Jul 05 '11 at 20:24
2

When UNICODE is defined for an MSVC project LPCTSTR is defined as const wchar_t *; simply changing the function signature will not work because whatever code within the function is using the input parameter expects a const char *.

I'd suggest you leave the function signature alone; instead call a conversion function such as WideCharToMultiByte to convert the string before calling your function. If your function is called several times and it is too tedious to add the conversion before every call, create an overload MyFunction(const wchar_t *wChar). This one can then perform the conversion and call the original version with the result.

Praetorian
  • 106,671
  • 19
  • 240
  • 328
2

This may not be totally on topic, but I wrote a couple of generic helper functions for my proposed wmain framework, so perhaps they're useful for someone.

Make sure to call std::setlocale(LC_CTYPE, ""); in your main() before doing any stringy stuff!

#include <string>
#include <vector>
#include <clocale>
#include <cassert>

std::string get_locale_string(const std::wstring & s)
{
  const wchar_t * cs = s.c_str();
  const size_t wn = wcsrtombs(NULL, &cs, 0, NULL);

  if (wn == size_t(-1))
  {
    std::cout << "Error in wcsrtombs(): " << errno << std::endl;
    return "";
  }

  std::vector<char> buf(wn + 1);
  const size_t wn_again = wcsrtombs(&buf[0], &cs, wn + 1, NULL);

  if (wn_again == size_t(-1))
  {
    std::cout << "Error in wcsrtombs(): " << errno << std::endl;
    return "";
  }

  assert(cs == NULL); // successful conversion

  return std::string(&buf[0], wn);
}

std::wstring get_wstring(const std::string & s)
{
  const char * cs = s.c_str();
  const size_t wn = mbsrtowcs(NULL, &cs, 0, NULL);

  if (wn == size_t(-1))
  {
    std::cout << "Error in mbsrtowcs(): " << errno << std::endl;
    return L"";
  }

  std::vector<wchar_t> buf(wn + 1);
  const size_t wn_again = mbsrtowcs(&buf[0], &cs, wn + 1, NULL);

  if (wn_again == size_t(-1))
  {
    std::cout << "Error in mbsrtowcs(): " << errno << std::endl;
    return L"";
  }

  assert(cs == NULL); // successful conversion

  return std::wstring(&buf[0], wn);
}

You could provide "dummy" overloads:

inline std::string get_locale_string(const std::string & s) { return s; }
inline std::wstring get_wstring(const std::wstring & s) { return s; }

Now, if you have an LPCTSTR x, you can always call get_locale_string(x).c_str() to get a char-string.


If you're curious, here's the rest of the framework:

#include <vector>

std::vector<std::wstring> parse_args_from_char_to_wchar(int argc, char const * const argv[])
{
  assert(argc > 0);

  std::vector<std::wstring> args;
  args.reserve(argc);

  for (int i = 0; i < argc; ++i)
  {
    const std::wstring arg = get_wstring(argv[i]);
    if (!arg.empty()) args.push_back(std::move(arg));
  }

  return args;
}

Now the main() -- your new entry point is always int wmain(const std::vector<std::wstring> args):

#ifdef WIN32

#include <windows.h>

extern "C" int main()
{
  std::setlocale(LC_CTYPE, "");

  int argc;
  wchar_t * const * const argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);

  return wmain(std::vector<std::wstring>(argv, argv + argc));
}

#else // WIN32

extern "C" int main(int argc, char *argv[])
{
  LOCALE = std::setlocale(LC_CTYPE, "");

  if (LOCALE == NULL)
  {
    LOCALE = std::setlocale(LC_CTYPE, "en_US.utf8");
  }

  if (LOCALE == NULL)
  {
    std::cout << "Failed to set any reasonable locale; not parsing command line arguments." << std::endl;
    return wmain(std::vector<std::wstring>());
  }

  std::cout << "Locale set to " << LOCALE << ". Your character type has "
            << 8 * sizeof(std::wstring::value_type) << " bits." << std::endl;

  return wmain(parse_args_from_char_to_wchar(argc, argv));
}

#endif
Community
  • 1
  • 1
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
1

In this example I convert a LPCTSTR to a const char pointer and a char pointer. For this conversion you need to include windows.h and atlstr.h, I hope to help you.

// Required inclusions
#include <windows.h>
#include <atlstr.h>

// Code
LPCTSTR fileName = L"test.txt";
CStringA stringA(fileName);
const char* constCharP = stringA;
char* charP = const_cast<char*>(constCharP);
Juan Carlos
  • 131
  • 1
  • 6