WINDOWS api can't resolve external symbol [duplicate] - c++

This question already has answers here:
error: cannot convert 'const wchar_t [13]' to 'LPCSTR {aka const char*}' in assignment
(3 answers)
Closed 6 years ago.
Does anyone have any idea why this is happening?
#define _x64
#include <Windows.h>
#include <iostream>
#include <windef.h>
#include <Winuser.h>
#include <tchar.h>
using namespace std;
int WINAPI MessageBoxW(
_In_opt_ HWND hWnd,
_In_opt_ LPCTSTR lpText,
_In_opt_ LPCTSTR lpCaption,
_In_ UINT uType
);
int main(){
std::cout << MessageBoxW(NULL, L"", L"", 0);
}
I am using compiling with Microsoft (R) Incremental Linker Version 14.00.24215.1 and using the "/EHsc" option at the command line for a command line input of "cl /EHsc winbasicb.cpp". I am not doing anything fancy I feel. Just using the /EHsc option for optimized compilation and linking.
I am getting this error.
/out:winbasicb.exe
winbasicb.obj
winbasicb.obj : error LNK2019: unresolved external symbol __imp_MessageBoxW referenced in function main
winbasicb.exe : fatal error LNK1120: 1 unresolved externals
I have read error: cannot convert 'const wchar_t [13]' to 'LPCSTR {aka const char*}' in assignment, but that was not helpful because they're getting a compiler error but I'm getting a linker error. In that question, the error was due to using MessageBoxW(..., "", "", ...) instead of MessageBoxW(..., L"", L"", ...), but I used L"" as I should but I'm getting a linker error.

In Windows there are two versions of just about all Windows API functions.
If you see the "Requirements" section of this reference page you will see that there is one MessageBoxW and one MessageBoxA function. The symbol MessageBox is a macro defined as one of the actual functions depending on the UNICODE macro.
The MessageBoxW function expects the strings to be wide-character strings, which is what you pass. Unfortunately it seem you don't have the correct Unicode settings, so the ANSI (narrow character, plain char) version MessageBoxA is used instead.
There are two solutions: Either make sure you have the correct Unicode settings. Or by explicitly call MessageBoxW. Or don't use wide-character strings (i.e. drop the L prefix).

You are calling the TCHAR version of MessageBox(). The conversion error message is complaining that you are passing Unicode strings to MessageBoxA(), which expects Ansi strings instead. This means your project is being compiled without UNICODE defined, thus TCHAR maps to char and MessageBox() maps to MessageBoxA(). But the L prefix is used to create Unicode literals, not Ansi literals.
When passing string literals to TCHAR based functions, use the TEXT() macro to ensure proper character encoding:
int msgboxID = MessageBox(
NULL,
TEXT("temp.txt already exists.\nDo you want to replace it?"),
TEXT("Confirm Save As"),
MB_ICONEXCLAMATION | MB_YESNO
);
Otherwise, stay away from the TCHAR functions (TCHAR should only be used when compiling the same codebase for both Win9x/ME and NT4+ Windows families), use the Ansi or Unicode functions directly instead:
int msgboxID = MessageBoxA(
NULL,
"temp.txt already exists.\nDo you want to replace it?",
"Confirm Save As",
MB_ICONEXCLAMATION | MB_YESNO
);
int msgboxID = MessageBoxW(
NULL,
L"temp.txt already exists.\nDo you want to replace it?",
L"Confirm Save As",
MB_ICONEXCLAMATION | MB_YESNO
);

Related

Why does LoadLibrary fail whilst LoadLibraryA succeeds in loading a DLL? [duplicate]

This question already has answers here:
Cast to LPCWSTR?
(4 answers)
Closed 3 years ago.
I'm trying to load a DLL into C++ but was getting error code 126, which I think means the DLL couldn't be found. After some poking around I changed LoadLibrary to LoadLibraryA and suddendly it worked. However, I am at a complete loss as to why. I realise that I haven't provided the dll for this code to be runable but would be greatful if somebody could provide an explaination as to why this is happening? And prehaps an example of how to get LoadLibary working.
Broken version
#include <stdio.h>
#include <windows.h>
typedef char* (*gf_getCurrentLibraryVersion) ();
int main() {
gf_getCurrentLibraryVersion getVersion;
HINSTANCE hLib = LoadLibrary((LPCWSTR)"libsbnw.dll");
if (hLib) {
getVersion = (gf_getCurrentLibraryVersion)GetProcAddress(hLib, "gf_getCurrentLibraryVersion");
printf("Version = %s\n", getVersion());
}
else {
printf("Error loading dll: %d/n", GetLastError());
}
printf("Hit any key to continue\n");
getchar();
return 0;
}
Compiles and outputs
Error loading dll: 126/nHit any key to continue
to console
Working version
#include <stdio.h>
#include <windows.h>
typedef char* (*gf_getCurrentLibraryVersion) ();
int main() {
gf_getCurrentLibraryVersion getVersion;
HINSTANCE hLib = LoadLibraryA("libsbnw.dll");
if (hLib) {
getVersion = (gf_getCurrentLibraryVersion)GetProcAddress(hLib, "gf_getCurrentLibraryVersion");
printf("Version = %s\n", getVersion());
}
else {
printf("Error loading dll: %d/n", GetLastError());
}
printf("Hit any key to continue\n");
getchar();
return 0;
}
Compiles and outputs
version is: 1.3.4
The problem with your LoadLibrary((LPCWSTR)"libsbnw.dll") call is that your build environment converts that to a LoadLibraryW call, but the way you are trying to pass a wide-character string is wrong.
As you have it, you are simply casting a const char* pointer to a const wchar_t* pointer, which won't work (for example, it will interpret the initial "li" characters as a single 16-bit character).
What you need to do is specify the string literal as a wide character constant, using the L prefix:
HINSTANCE hLib = LoadLibrary(L"libsbnw.dll");
Or, alternatively, using the TEXT() macro (which will boil down to the same, when using the UNICODE build environment):
HINSTANCE hLib = LoadLibrary(TEXT("libsbnw.dll"));
Feel free to ask for further explanation and/or clarification.
Ordinarily the compiler will try to point out when you're making a mistake. But in this case you've told it not to by adding an explicit cast to the string.
HINSTANCE hLib = LoadLibrary((LPCWSTR)"libsbnw.dll");
//^^^^^^^^^
I'm assuming you've built your app with Unicode enabled, which defines a macro converting LoadLibrary to LoadLibraryW. The parameter must be a wide-character string.
HINSTANCE hLib = LoadLibraryW(L"libsbnw.dll");
There's another macro you can use when you're not sure if the app will be compiled with Unicode or not, TEXT() or the shorter form _T(). Not recommended for modern code since needing to turn Unicode on or off hasn't been a problem in many years, just use Unicode always.
HINSTANCE hLib = LoadLibrary(TEXT("libsbnw.dll"));

LPCSTR and wchar_t issue. Linker error because of parameter mismatch

I a porting a large amount of code from Visual Studio to mingw unicode enabled project and I ran into this issue.It seems that the parameters I am passing from the derived class to the base class do not match. Atleast thats my assumption. I am suspecting that the issue is with the type LPCSTR Looking into this type in mingw I get the follwoing typedef
typedef CONST CHAR *LPCSTR,*PCSTR;
Now this is the base class
#ifdef UNICODE
CBasePin(
__in_opt LPCSTR pObjectName,
__in CBaseFilter *pFilter,
__in CCritSec *pLock,
__inout HRESULT *phr,
__in_opt LPCWSTR pName,
PIN_DIRECTION dir);
#endif
This is the class that inherits from the base class and passes the parameters to the base class.
CAsyncOutputPin::CAsyncOutputPin(
HRESULT * phr,
CAsyncReader *pReader,
CAsyncIo *pIo,
CCritSec * pLock)
: CBasePin(
TEXT("Text Pin"),
pReader,
pLock,
phr,
TEXT("Output"),
PINDIR_OUTPUT
),
m_pReader(pReader),
m_pIo(pIo)
,m_bQueriedForAsyncReader(false) ////
{
}
This is the linker error I am getting at the constructor initialization list
undefined reference to `CBasePin::CBasePin(wchar_t const*, CBaseFilter*, CCritSec*, long*, wchar_t const*, _PinDirection)'|
any suggestions on why I am getting this linker error. I am a bit puzzled as to why this is a linker error. I was guessing if it was a type mismatch or something it would show up as a compiler error. Any suggestions on how I can resolve this issue for Mingw 64bit gcc ?
your CBasePin has a parameter LPCSTR pObjectName (which is of type const char*) and a parameter LPCWSTR pName (whichis of type const wchar_t*) and in your call to it you're using TEXT-macro on a char-literal ,so both those literals getting the L-prefix making them const wchar_t* when UNICODE is defined ,so there is a type mismatch on the pObjectName.
If UNICODE is not defined then you would get the same error but on pName.
Remove the first TEXT and it should be Ok (for UNICODE that is).
Why are you using the TEXT macro? You have one char * parameter and one wchar_t * parameter, and it can't do the right thing for both.
Just write what you mean. Something like
"Text Pin", ..., L"Output", ...

LPCWSTR error; is there a better solution?

I have the following c++ code, and it seems like everywhere I attempt to put a string, I have to convert it in order to avoid a `Cannot conver parameter 2 from 'const char[x] to LPCWSTR. I know I can fix this issue by doing a simple conversion, but is there any way around having to convert practically every string I provide? I am a c# developer learning c++ so I'm guessing I'm missing some fundamental concept of the language, if someone could shed some light on this, I'd be grateful!
#include <Windows.h>
#include <string>
using namespace std;
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PSTR cmdLine,
int showCmd)
{
MessageBox(0, "First Win32 Program.", "My App", MB_OK);
}
Is there a better solution than just this:
{
MessageBox(0, (LPCWSTR)"First Win32 Program.", (LPCWSTR)"My App", MB_OK);
}
And for some odd reason my application is coming up in Japanese or Chinese. So lost on this one.
Use L"text" to create your strings. This way you're creating a wide string which most-likely are expected from the WinAPI.
#include <Windows.h>
#include <string>
using namespace std;
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PSTR cmdLine,
int showCmd)
{
MessageBox(0, L"First Win32 Program.", L"My App", MB_OK);
}
The problem is you're injecting a narrow string by using a C-style cast to LPCWSTR. So two of your narrow chars (8 bit each) will end mixed-up in one UNICODE char (16 bit each).
You should use the L prefix with your literals. The WINAPI works mostly with wide strings.
As for why that prefix works, here's the relevant part in the standard (§2.14.5/11):
A string literal that begins with L, such as L"asdf", is a wide string literal. A wide string literal has type
“array of n const wchar_t”, where n is the size of the string as defined below; it has static storage duration
and is initialized with the given characters.
The garbage you get is because you're doing a cast that doesn't mean anything, and end up with garbage data that the library tries to interpret as a wide string.
Indeed, here's what a LPCWSTR:
typedef const wchar_t* LPCWSTR;

c++ build errors on win32 school application

I haven't been programming in c++ very long, but need to make an Win32 application for my school. The teacher helped me a lot with information but after a few days of trying I am still stuck.
Errors:
error C2440: '=' : cannot convert from 'const char [11]' to 'LPCWSTR'
error C2664: 'CreateWindowExW' : cannot convert parameter 2 from 'const char [11]' to 'LPCWSTR'
error C2664: 'TextOutW' : cannot convert parameter 4 from 'char *' to 'LPCWSTR'
IntelliSense: argument of type "char *" is incompatible with parameter of type "LPCWSTR"
Don't know if all the other suff is right, but i only get those 4 error now
cpp file:
/* Hoofdstuk 10, User Interface */
#include "Callback_NYCM.h"
// UI
int WINAPI WinMain(HINSTANCE thisInstance,HINSTANCE prevInstance,LPSTR lpCmdLine,int nShowCmd)
{
PAINTSTRUCT ps;
HDC hdc;
MSG msg;
HWND hwnd;
WNDCLASSEX wndclassex; //struct_WNDCLASSEX via windows.h
// toekenning
wndclassex.cbSize = sizeof(WNDCLASSEX);
wndclassex.style = CS_HREDRAW | CS_VREDRAW;
wndclassex.lpfnWndProc = WndProc;
wndclassex.cbClsExtra = 0;
wndclassex.cbWndExtra = 0;
wndclassex.hInstance = thisInstance;
wndclassex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclassex.hCursor = LoadCursor(thisInstance,IDC_ARROW);
wndclassex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wndclassex.lpszMenuName = NULL;
wndclassex.lpszClassName = "WNDCLASSEX";
wndclassex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
// functie aanroep
RegisterClassEx(&wndclassex);
// IfThen -> CreateWindows
if(!(hwnd = CreateWindowEx(NULL,"WNDCLASSEX","Hoofdstuk 10",WS_OVERLAPPEDWINDOW
| WS_VISIBLE,50,50,650,300,NULL,NULL,thisInstance,NULL)))
{
return 0;
}
// logische structuur
while(GetMessage(&msg, NULL, 0, 0))
{
if(msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
};
header file:
/*Hoofdstuk 10, Deelnemer.h*/
//Declaratie
class Deelnemer
{
private:
char* nm;
public:
//Constructor
Deelnemer(){
}
//Methoden = prototype
void Deelnemer::Invoeren();
char* Deelnemer::WeergevenNaam();
};
//Implemenmtatie.Invoeren
void Deelnemer::Invoeren()
{
nm = "Roy";
}
//.Weergeven
char* Deelnemer::WeergevenNaam()
{
return nm;
}
callback_NYCM.h:
/*Hoofdstuk 10, Callback_NYCM*/
#include "Windows.h"
#include "Deelnemer.h"
// prototype
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam);
//Implementatie
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)
{
//Constructie
PAINTSTRUCT ps;
HDC hdc;
MSG msg;
WNDCLASSEX wndclassex;
// HWND hwnd;
Deelnemer deelnemer1;
//UI
switch(message)
{
case WM_PAINT:
{
//Functieaanroep.Initialisatie
deelnemer1.Invoeren();
//.TextOut
TextOut(hdc,50,50,deelnemer1.WeergevenNaam(),
strlen(deelnemer1.WeergevenNaam()));
EndPaint(hwnd,&ps);
return 0;
}
break;
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
break;
default:
{
return DefWindowProc(hwnd,message,wparam,lparam);
}
break;
}
return 0;
}
I think my constructor or something like that is wrong and my return value for char* Deelnemer::WeergevenNaam()
Could somebody explain me what is wrong in my code so I know how to get it working?
UPDATE:
Updating your application requires to use UNICODE string literals
throughout, i.e. L"MyString" instead of "MyString". You also need to
use WCHAR/wchar_t in place of char
But how do i do this with my code, could somebody help?
UPDATE 2:
That solved al lot of errors!
But i have some more errors left in this part
Deelnemer deelnemer1;
switch(message)
{
case WM_PAINT:
{
//Functieaanroep.Initialisatie
deelnemer1.Invoeren();
//.TextOut
TextOut(hdc,50,50,deelnemer1.WeergevenNaam(),
strlen(deelnemer1.WeergevenNaam()));
EndPaint(hwnd,&ps);
return 0;
}
so the errors are on line: deelnemer1.WeergevenNaam()
-TextOutW' : cannot convert parameter 4 from 'char *' to 'LPCWSTR'
-IntelliSense: argument of type "char *" is incompatible with parameter of type "LPCWSTR"
UPDATE 3:
After some testing i found a solution (like you guys said below) But now i only got this one left:
TextOut (hdc,50,50,deelnemer1.WeergevenNaam(), // on the deelnemer1.weergevenNaam()
with error C2664: 'TextOutW' : cannot convert parameter 4 from 'const char *' to 'LPCWSTR'
Your code is written to compile as ANSI but your solution settings include _UNICODE/UNICODE. You can either set your solution to use ANSI encoding by changing Character Set (on the General node of the Configuration Properties) from Use Unicode Character Set to Use Multi-Byte Character Set or update your application code (the latter is recommended).
Updating your application requires to use UNICODE string literals throughout, i.e. L"MyString" instead of "MyString". You also need to use WCHAR/wchar_t in place of char (where applicable) and call the wide versions of the Windows API. For many API calls there exists a wide version that has a W at the end, e.g. CreateWindowExW. If you are using the Standard C++ Library you will also want to make sure to use the UNICODE variants where character encoding is necessary (e.g. std::wstring instead of std::string). Additional information can be found at Text and Strings in Visual C++.
A bit more background about what is going on here: The Windows API and Microsoft's CRT implementation can be used to compile code using ANSI/Multi-Byte character set or UNICODE character set. To support both character encodings the C/C++ preprocessor replaces the respective character types and API calls with the specific implementations depending on whether or not the _UNICODE and UNICODE preprocessor symbol is defined.
For example, the call CreateWindowEx is expanded to either CreateWindowExA or CreateWindowExW. Both implementations have different parameter types for string arguments (char* and wchar_t* respectively). To use ANSI/Multi-Byte encoding the call would be CreateWindowExA(NULL,"WNDCLASSEX",...). For UNICODE it would look like CreateWindowExW(NULL,L"WNDCLASSEX",...).
To see what the code looks like after the preprocessor is through you can use the /P or /E compiler switches (assuming you're using the Microsoft Compiler).
Note: Don't forget to read The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!).
simple answer - with no explanation of why
change quoted strings to L"foo"
change char to wchar_t
LPCWSTR -> Long Pointer to Constant Wide Character String.
All of your error messages reduce to some form of char[XX] is not the same type as wchar_t[XX].
Microsoft's Win32 API's are designed to compile either with ANSI strings, char, or wide character strings, wchar_t. This is why many Win32 function have two signatures, one ending in A, the other in W.
Example:
CreateWindowExW
CreateWindowExA
CreateWindowEx - A macro that expands to one of the above signatures depending on your build configuration. If you define UNICODE or _UNICODE it will expand to the W version.
Typically you use the macros when you are programming in Win32, and wrap all of your string literals with the _T macro. When defining character arrays that are strings, you'll want to use LPCTSTR and LPTSTR. These are also macros which will expand to either char * or wchar_t * depending on your build settings.
I have it working. The use wchar_t * and L"string". The problem with my code was more the structure because copy/pasting to a new project solved my errors. Thanks guys!
By choosing "not set" on Character Set in Project > Property > Configuration Properties > General, I was able to remove errors C2440 and C2264.

cannot convert const wchar_t to 'const_char' for argument 2 in MessageBOX etc etc

I'm learning DirectX for a project for university, My compiler however shows this error:
"10 C:\Dev-Cpp\projectdirectx\main.cpp cannot convert `const wchar_t*' to `const CHAR*' for argument `2' to `int MessageBoxA(HWND__*, const CHAR*, const CHAR*, UINT)'"
I don't understand this at all, I don't know what I did wrong, What i'm attempting to do is a simple messagebox, Here's the code:
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd)
{
MessageBox(NULL, L"testing testing",
L"C++", MB_OK);
return 0;
}
What do I do?
You are building an ANSI build, but using a Unicode literal. Either use regular string literals (drop L prefix in front), or switch to a Unicode build.
Just remove the L prefix from the strings.
The problem is that you are trying to invoke wide character version of MessageBox function, which is not the case in your build environment. Just remove the L macro in the function call and it should work.