Given the following piece of code:
#include <stdlib.h>
int _tmain(int argc, _TCHAR* argv[])
{
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char fname[_MAX_FNAME];
char ext[_MAT_EXT];
_splitpath_s( argv[0], drive, dir, fname, ext);
// ...some more code...
}
The compiler throws the following error:
error 2665: '_splitpath_s' none of the 2 overloads could convert all the argument types
What is going wrong? I'm using VS 2010 SP1.
Thanks a lot in advance.
If _UNICODE is defined, then _TCHAR is wchar_t, so argv[0] is a wchar_t*, which is not convertible to char const* (this is the type of the first parameter of _splitpath_s.
The Error List in Visual Studio only shows the first line of each error, for brevity. The full error from the compiler, which you can find in the Output window, is more informative:
error C2665: '_splitpath_s' : none of the 2 overloads could convert all the argument types
[...]\stdlib.h(797): could be 'errno_t _splitpath_s<3,256,256,256>(const char *,char (&)[3],char (&)[256],char (&)[256],char (&)[256]) throw()'
while trying to match the argument list '(_TCHAR *, char [3], char [256], char [256], char [256])'
In the full error, it is obvious that the only argument whose type might not match is the first one, since the others clearly match.
If you are going to use _TCHAR, then use it and its friends everywhere. Your arrays should be arrays of _TCHAR and you should use _tsplitpath_s. Alternatively, don't use _TCHAR at all and just use either narrow or wide character strings throughout your project (on Windows, wide strings are preferable)
If you are using C, then
/* _splitpath(path_buffer, drive, dir, fname, ext); */
_splitpath_s(path_buffer, drive, _MAX_DRIVE, dir,
_MAX_DIR, fname, _MAX_FNAME, ext, _MAX_EXT);
If using C++, there isn't any reason to use _tmain if you are not using _TCHAR for drive, dir, etc or you should be using _tsplitpath_s instead. Or convert all of them to ANSI or UNICODE.
This works for me:
wchar_t dir[_MAX_DIR] = {0};
wchar_t drive[_MAX_DRIVE] = {0};
wchar_t fname[_MAX_FNAME] = {0};
wchar_t ext[_MAX_EXT] = {0};
errno_t err;
std::wstring path = L"c:\\this\\is\\a\\test.exe";
err = _wsplitpath_s(path.c_str(),&drive[0],_MAX_DRIVE,&dir[0],_MAX_DIR,&fname[0],_MAX_FNAME,&ext[0],_MAX_EXT);
Related
This question already has answers here:
Argument of type "char *" is incompatible with parameter of type "LPWSTR"
(2 answers)
Closed 6 years ago.
The following code
string exePath() {
string path;
char buffer[MAX_PATH];
cout << "reading path\n";
GetModuleFileName(NULL, buffer, MAX_PATH);
string::size_type pos = string(buffer).find_last_of("\\/");
path = string(buffer).substr(0, pos)/*+"\\system.exe"*/;
return path;
}
gives me error at the second parameter in VisualStudio (buffer):
the type "char *" argument is incompatible with the type parameter
"LPWSTR"
(translated from italian,i have vs in italian, hope you understand)
and
can't convert Char to LPWSTR in the 2 argument
This code compiles fine with code::blocks and dev c++ but in vs it doesn't
Because GetModuleFileName is a macro definition for GetModuleFileNameW if UNICODE is defined and which requires wchar_t*. If no UNICODE is defined then GetModuleFileName resolves to GetModuleFileNameA. The simple fix for you is to use explicitly GetModuleFileNameA which accepts char*
This code compiles fine with code::blocks and dev c++ but in vs it doesn't
most probably because with code::blocks you compile with no UNICODE defined, while under VS by default UNICODE is defined.
If you are not using UNICODE, and want to stay with multibyte string (same as in code::blocks) you can disable UNICODE in your Visual Studio build by changing in project properties on General tab -> Character set to Use Multi-Byte Character Set.
[edit]
To avoid problems with UNICODE characters in the path it is recomended to use UNICODE. This requires you to use std::wstring which is specialization for wchar_t, also instead of char buffer[MAX_PATH]; you should use wchar_t buffer[MAX_PATH];. cout << "reading path\n"; would have to be wcout << L"reading path\n";. You can also use macros like TCHAR or _T("reading path"), to make it independently work for UNICODE and non-UNICODE builds.
I believe this is related How I can print the wchar_t values to console?. You must also prefix your strings with L to make them wide-char like this
std::wcout << L"reading path" << std::endl;
This will work well if your application is for Windows only, but you should use the TEXT("reading path") macro style otherwise, because even though it's not there by default for other platforms, you can add it easily.
This has probably been asked before but I can't seem to find the solution:
std::string GetPath()
{
char buffer[MAX_PATH];
::GetSystemDirectory(buffer,MAX_PATH);
strcat(buffer,"\\version.dll");
return std::string(buffer);
}
This returns an error stating:
argument of type "char *" is incompatible with parameter of type "LPWSTR"
So yeah. Anyone got an answer?
You need to use the ansi version:
std::string GetPath()
{
char buffer[MAX_PATH] = {};
::GetSystemDirectoryA(buffer,_countof(buffer)); // notice the A
strcat(buffer,"\\version.dll");
return std::string(buffer);
}
Or use unicode:
std::wstring GetPath()
{
wchar_t buffer[MAX_PATH] = {};
::GetSystemDirectoryW(buffer,_countof(buffer)); // notice the W, or drop the W to get it "by default"
wcscat(buffer,L"\\version.dll");
return std::wstring(buffer);
}
Rather than call the A/W versions explicitly you can drop the A/W and configure the whole project to use ansi/unicode instead. All this will do is change some #defines to replace foo with fooA/W.
Notice that you should use _countof() to avoid incorrect sizes depending on the buffers type too.
If you compile your code using MultiByte support it will compile correctly,but when you compile it using Unicode flag it will give an error because in Unicode support ::GetSystemDirectoryA becomes ::GetSystemDirectoryW use consider using TCHAR instead of char.TCHAR is defined such that it becomes char in Multibyte flag and wchar_t with Unicode flag
TCHAR buffer[MAX_PATH];
::GetSystemDirectory(buffer,MAX_PATH);
_tcscat(buffer,_T("\\version.dll"));
You can use typedef for string /wstring so your code becomes independent
#ifdef UNICODE
typedef wstring STRING;
#else
typedef string STRING;
#endif
STRING GetPath()
{
TCHAR buffer[MAX_PATH];
::GetSystemDirectory(buffer,MAX_PATH);
_tcscat(buffer,_T("\\version.dll"));
return STRING(buffer);
}
#include <windows.h>
#include <iostream>
using namespace std;
int main() {
char* file="d:/tester";
WIN32_FIND_DATA FindFileData;
HANDLE hFind;
hFind = FindFirstFile(file, &FindFileData); // line of error says argument of type char* is incompatible with parameter of type LPCWSTR
}
I can't understand the error.What is it and how can I solve the error?
I am making a console app and need to check if files are in there in the directory .
the type LPCWSTR is a const pointer to wide char
the file in char* file="d:/tester"; is a pointer to an ordinary char
Ordinary char usually uses 1 byte of memory, while wide char usually uses 2 bytes. What will happen if the file name contains cyrillic or japanese letters? You will not be able to open it without specifying the encoding. Windows API accepts wide chars to FindFirstFile function, because file name can be in a unicode. So, if you write L"foo_bar" the compiler will interpret it as wide character string. Therefore you can write wchar_t* file = L"d:\\tester"; to match parameter types, so compilation will be successful.
You are calling function that expects wide character string (FindFirstFileW). You either change file to use wchar_t* file = L"d:\\tester"; or use an ASCII version of the function FindFirstFileA.
You are compiling with UNICODE defined and yet passing an ANSI string as your first parameter. Replace your line that beings char * with
TCHAR *file=TEXT("d:\tester");
and things should be fine.
Martyn
I keep getting this error:
cannot convert parameter 1 from 'char' to 'LPCWSTR'
int main(int argc, char argv[])
{
// open port for I/O
HANDLE h = CreateFile(argv[1],GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
if(h == INVALID_HANDLE_VALUE) {
PrintError("E012_Failed to open port");
can someone help?
Go to the Properties for your Project and under Configuration Properties/General, change the Character Set to "Not Set". This way, the compiler will not assume that you want Unicode characters, which are selected by default:
It should be
int main(int argc, char* argv[])
And
HANDLE h = CreateFileA(argv[1],GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
This is the main function that Visual Studio creates by default:
int _tmain(int argc, _TCHAR* argv[])
Where _TCHAR is defined to be char or wchar_t depending if _UNICODE is defined or not. The same thing happens with API functions. I would advise you against using explicit CreateFileA. Change your main and use CreateFile.
Depending on your compiler setting for CharacterSet, you may need to perform a multibyte / widechar conversion, or change the CharacterSet if you don't care what it is.
For converting with MultiByteToWideChar, see the following...
http://www.codeguru.com/forum/showthread.php?t=231165
I guess you're compiling with Unicode enabled. Then with char argv[], argv is a char array, so argv[1] is a char, and CreateFile wants a const wchar_t* as first parameter, not a char.
That said, your main definition is also broken, it should have char* argv[]. With that change, you can call CreateFileA.
I have been reading one of the Hoglund titles and I though, reading great, but can I make it work? Why do they provide non-working examples in books?
#include "stdafx.h"
#include <cstdio>
#include <windows.h>
#include <winbase.h>
#include <tlhelp32.h>
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hProcess;
DEBUG_EVENT dbg_evt;
int aPID;
if(argc != 2)
{
printf("wrong number of params\nusage %s<pid>\n", argv[0]);
return 0;
}
//load the ptr to fDebugSetProcessKillOnExit
fDebugSetProcessKillOnExit = (DEBUGSETPROCESSKILLONEXIT)
GetProcAddress(GetModuleHandle("kernel32.dll"),
"DebugSetProcessKillOnExit");
if(!fDebugSetProcessKillOnExit)
{
printf("[!] failed to get fDebugSetProcessKillOnExit function!\n");
}
aPID = atoi(argv[1]);
}
I am getting two error messages:
fDebugSetProcessKillOnExit is an undeclared identifier
What type should it be?
"Error 4 error C2664: 'GetModuleHandleW' : cannot convert parameter 1 from 'const char [13]' to 'LPCWSTR'
What type should the fDebug... be? Why doesn't the aPid = atoi... line work?
Should the project be compiled in C instead of C++, as this is exactly as it is in the book?
Thanks, R.
Taking this from MSDN:
BOOL WINAPI DebugSetProcessKillOnExit(__in BOOL KillOnExit);
you can declare the function pointer as:
BOOL (*fDebugSetProcessKillOnExit)(BOOL) = /* ... */;
or ease your eyes by using typedef:
typedef BOOL (*DebugKillPtr)(BOOL);
DebugKillPtr fDebugSetProcessKillOnExit = /* ... */;
Function pointers can be somewhat confusing, InformITs guide on them should help with that.
Additionally, you are using a Unicode build. You can either use GetModuleHandle(L"Kernel32.dll") or _T() etc. or set your project to use the multi-byte-character-set (project properties -> configuration -> general -> character set).
The unicode-character-set is also the reason why the atoi() statement can't work:
argv is an array of _TCHAR*s, and _TCHAR is wchar_t for unicode-builds. atoi() however expects a const char* argument and you are handing it a wchar_t*.
So you can either again use a multi-byte-character set, convert the string or use Microsofts _wtoi()/_ttoi().
To ease switching between character sets and stick with the style of the book, prefer the _T* and _t* versions.
The declaration for fDebugSetProcessKillOnExit is missing; probably it should be something like
DEBUGSETPROCESSKILLONEXIT fDebugSetProcessKillOnExit;
where DEBUGSETPROCESSKILLONEXIT should be a typedef to the prototype of that function.
You are compiling in Unicode and the book "thinks" that you're compiling in ANSI; you should change the strings passed to the APIs to generic strings with the _T() macro.
So, to sum everything up, you should simply change one line and add the typedef:
typedef BOOL (*DEBUGSETPROCESSKILLONEXIT)(BOOL);
//load the ptr to fDebugSetProcessKillOnExit
DEBUGSETPROCESSKILLONEXIT fDebugSetProcessKillOnExit = (DEBUGSETPROCESSKILLONEXIT) GetProcAddress(GetModuleHandle(_T("kernel32.dll")), _T("DebugSetProcessKillOnExit"));