I've tried making a minimal testcase to reproduce it, but haven't been able to.
Adding a screenshot to show the error
this is the call to the SetClass function
m_luaState["MyClass"].SetClass<MyClass, I32>("AddTo", &MyClass::Add);
This is the MyClass:
class MyClass
{
public:
MyClass(I32 i) : m_i(i), m_j(2*i)
{
}
I32 m_j;
void Add(I32 iv)
{
std::cout << iv + m_i + m_j;
}
private:
I32 m_i;
};
Your RegisterClass(...) method name is being replaced by a Windows #define RegisterClass. Since you are compiling as ANSI, you are picking up the ANSI alias for RegisterClass which is RegisterClassA (it would be RegisterClassW if you were compiling Unicode).
You could either rename your RegisterClass(...) method if that's a viable option, exclude the conflicting Windows header (probably not an option), or conditionally #undef RegisterClass at the top of your header which declares your RegisterClass(...) method, something like:
#ifdef RegisterClass
#undef RegisterClass
#endif
Some additional reference about the conflicting symbol: RegisterClass function
This problem is actually quite interesting, and is nothing you have done wrong. It's because the RegisterClass Windows function and how Windows handle Unicode when programming.
Windows have two variants for almost all its function, if you see the table at the bottom of the linked MSDN reference you will see them mentioned as RegisterClassW and RegisterClassA. The W function is used for Unicode builds, where all strings and characters are of type wchar_t. The A variant is the "ANSI" variant, using normal char characters.
The problem here is that Windows uses macros to decide which of the funcitons to use, basically it does this
#ifdef UNICODE
# define RegisterClass RegisterClassW
#else
# define RegisterClass RegisterClassA
#endif
This is problematic because the preprocessor will replace your call to the RegisterClass member function with the RegisterClassA symbol, leading to your error.
The simple solution is to #undef the RegisterClass macro directly after including <windows.h> (or in some other suitable place). Another is to rename RegisterClass to something which doesn't clash with the Windows function.
Related
I have an Unreal Engine 4 project with several plugins. On of these plugins contains a FileHelper class with a method CreateFile. This has worked fine for months, but in a recent commit, a different plugin added a call to FileHelper::CreateFile and now sometimes I get a linker error saying that CreateFileW is not a member of FileHelper (this doesn't appear in every build, which I cannot yet explain).
I went on to undefine CreateFile temporarily like this
#include "UtilPlugin/File/FileSystemHelper.h"
#ifdef _WIN32
#pragma push_macro("CreateFile")
#undef CreateFile
#endif //_WIN32
...//new code including CreateFile call
#ifdef _WIN32
#pragma pop_macro("CreateFile")
#endif //_WIN32
but now I get errors
C2039 'CreateFile': is not a member of 'FileSystemHelper'
C3861 'CreateFile': identifier not found
Since I know CreateFile is successfully called in other places (at least within the same plugin as the FileSystemHelper), I know that it exists.
Thus my question is, if the undefine can affect member functions like this.
I have moved the #undef part above the includes in code and I don't get an error anymore, but since it occurred seemingly randomly, I'm not entirely sure that I really fixed the problem.
Following shows a problematic case:
#define CreateFile CreateFileW
struct S
{
void CreateFile(); // Actually void CreateFileW();
};
And then
#undef CreateFile
void foo()
{
S s;
s.CreateFile(); // Error, "expect" s.CreateFileW()
}
As #define might modify meaning of code (locally), #undef "cancels" that modification locally too.
I have a member function that returns a reference to a CString member of the class. It looks something like this:
const CString& GetDateFormat() const { return MyString; }
I am using Visual Studio 2015 and whenever I type this function, the IDE automatically changes it to GetDateFormatA(). When I go to the function definition and hover over the function name I see this:
#define GetDateFormat GetDateFormatA
So it's like VS automatically created this macro.
The function works fine but I have already seen this multiple times (I mean a function — written by others — with a macro renaming it by appending an A) and I am quite curious and a bit confused. What's the purpose? Is it something related to character encoding or at least to strings?
GetDateFormat is a WinAPI function which takes at least one parameter whose type involves TCHAR (in this case, it's the parameters LPCTSTR lpFormat and LPTSTR lpDateStr). All such WinAPI functions actually exist in two forms: one with an A appended, and one with W appended. The A variant is used when TCHAR means char, and the W one is used when TCHAR means wchar_t. To support this, <windows.h> actually defines a macro for each such function, resolving to one or the other based on whether _UNICODE is defined. In your case, there's a definition somewhere in WinAPI headers similar to this:
#ifdef _UNICODE
# define GetDateFormat GetDateFormatW
#else
# define GetDateFormat GetDateFormatA
#endif
This is where your program's occasional reference to GetDataFormatA comes from. You can read more about working with TCHARs on MSDN.
How to solve this depends on whether you need to call WinAPI's GetDateFormat and use its char/wchar_t distinction. If so, you will have to rename your function. However, my impression is that you're not interested in the WinAPI function. In that case, a solution would be to add the following lines to your header which declares your GetDateFormat:
#include <windows.h>
#undef GetDateFormat
That way, nobody consuming your header will see the macro and GetDateFormat will remain GetDateFormat.
I am looking for the most fool-safe way to pass a VB6 boolean variable to a function (written in C++, stdcall).
The C++ function will set the "bool" variable of a struct using this VB6 variable.
I have tried declaring it like this in C++:
extern "C" __declspec(dllexport) int SetParameter( BOOL bErrorView)
{
DLL_sSettings nSet;
nSet.bErrorView =(bErrorView != FALSE);
int ret = stSetParameter(sizeof(DLL_sSettings), nSet);
return (ret);
}
stSetParameter is declared as
extern "C" int ST_COMDLL_API stSetParameter(int DataLen, DLL_sSettings Settings);
The DLL_sSetting is declared as
typedef struct
{
bool bErrorView; // true: Show
// false: Don't show
(...)
} DLL_sSettings;
However, I am unable to get it to work.
I call it in VB6 using
Private Declare Function SetParameter Lib "MyDLL.dll" Alias "_SetParameter#4" (ByVal bErrorView As Boolean) As Long
But it does not work as expected, I guess somewhere the VB6 Boolean gets lost or is being incorrectly converted.
I am currently using VB6 Boolean, C++ BOOL and C++ bool.
I know that is not so nice, but I don't see any other way.
Does anybody spot something wrong in my code?
VB6 uses the StdCall calling convention by default (cdecl convention is supported if you create a type library with a module section describing your imports, instead of using Declare Function). And C++ supports a whole host of calling conventions: stdcall, fastcall, cdecl, thiscall.
It is important to note that calling functions using stdcall in another library is not enough to change your functions to stdcall. You can use a command-line switch to the compiler, but the most robust is to include the __stdcall keyword in your source code. It gets applied to the name of the function, like so:
int __stdcall functionname(int args);
Since you will also want to export those functions for VB6 to find them, you'll want extern "C" to reduce name mangling, and __declspec(dllexport) to place them in the exports table.
It's pretty common to use a macro to do all of the above at once. It looks like the library you are wrapping does this with ST_COMDLL_API. Inside the library, that will expand to __declspec(dllexport) __stdcall. For consumers, it will use dllimport instead.
Any time you are defining an API to be used across different compilers (or even different languages), it's a good idea to be very explicit about calling convention and structure packing (#pragma pack). Otherwise you are at the mercy of options specified in the project file and other headers files. Even if you are happy with the defaults the compiler uses, your public headers should be explicit, because eventually someone will try to use two libraries in the same program, and the other library may demand changes to the compile options.
BOOL is type definition for int.
it declared in windef.h as follows:
typedef int BOOL;
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
bool is C++ type, which can't be used in function prototype if you declare function with extern "C".
so VB should treat BOOL as Long (32 bit integer), not as Bolean. 0 means false otherwise (usually 1) it is true.
I am migrating from Visual Studio 6 to Visual Studio 2008 and I have a function of a component I am using named SetDefaultPrinter.
Unfortunately there is a windows library function now, SetDefaultPrinter, with the same name. And the macro associated with it is getting in the way of me using my function.
This is my workaround I have to call my function:
#undef SetDefaultPrinter
pNova->SetDefaultPrinter();
#ifdef UNICODE
#define SetDefaultPrinter SetDefaultPrinterW
#else
#define SetDefaultPrinter SetDefaultPrinterA
#endif // !UNICODE
Is there a less ugly way around this? And no, I do not have control over that external component to change the name of the function.
This is why C++ added namespaces; too bad the Windows definitions can't use them.
In another source module, where you do NOT include windows.h or any other Windows include files, generate a stub function to call your clashing function.
void MySetDefaultPrinter(CNova * pNova)
{
pNova->SetDefaultPrinter();
}
You could use a wrapper around the external component. This is sometimes called the "Adapter" pattern.
// header file
class NovaWrapper
{
Nova *_nova;
public:
void setDefaultPrinter();
};
// implementation file - this file does not include windows.h - you need to make sure it
// does not have visibility of the "bad" SetDefaultPrinter macro
void NovaWrapper::setDefaultPrinter()
{
_nova->SetDefaultPrinter();
}
Now, modify your client code to use NovaWrapper instead of the underlying instance.
This was, in the end, fixed by simply swapping the order of includes. Apparently, the developers of this component realized the problem before me, so they included SetDefaultPrinterA and SetDefaultPrinterW in the component that are just aliases for SetDefaultPrinter. So that if windows.h renames the function, it's not a problem.
I am developing a multi-platform application and in one component I have a class method called DrawText. Unfortunately, I get a linker error (on windows only) saying that there is an unresolved external symbol for a DrawTextW method of this class.
I've seen this before with other methods ending in "Text" where it is looking for either a FooTextW or FooTextA method instead of the FooText method I defined. My assumption is that somewhere in the Windows headers there is a macro definition assigning FooText to FooTextW or FooTextA based on some other definition.
Aside from renaming my function (which is what I did in the past), does anybody have any good ideas for getting around this issue?
Thanks.
Joe
You really only have two choices:
#ifdef DrawText
#undef DrawText
#endif
Or rename your function. Win32 uses macros which have no namespacing or scoping, so you're kinda stuck.
We just re-name our functions.
BTW: It's based on #ifdef UNICODE usually (or _UNICODE or a few other variants).
Yes, this is a real problem with using Windows, and there's no way to turn it off since the headers all look like this:
#ifdef UNICODE
#define GetDlgItemText GetDlgItemTextW
#else
#define GetDlgItemText GetDlgItemTextA
#endif
So you're going to get the symbol defined either way. It would be very nice if you could #define something before #include'ing windows.h that turns this behavior off, but alas none exists.