Rapidjson: no member as GetObject

Created on 8 Feb 2019  路  7Comments  路  Source: Tencent/rapidjson

I want to get Object just like in tutorial:

http://rapidjson.org/md_doc_tutorial.html

document.GetObject()

However it gives me this error:

no member named GetObjectA in rapidjson::GenericDocument

I cannot use GetObject() with neither rapidjson::Document, nor rapidjson::Value, etc.

How could I use GetObject()?

Most helpful comment

This is most likely because of the GetObject macro defined in the windows headers (in wingdi.h):

WINGDIAPI int   WINAPI GetObjectA(__in HANDLE h, __in int c, __out_bcount_opt(c) LPVOID pv);
WINGDIAPI int   WINAPI GetObjectW(__in HANDLE h, __in int c, __out_bcount_opt(c) LPVOID pv);
#ifdef UNICODE
#define GetObject  GetObjectW
#else
#define GetObject  GetObjectA
#endif // !UNICODE

Long time ago some genius at microsoft thought it was a good ideal to redefine the meaning of GetObject in the whole world. When "windows.h" is included systematically, there is no problem as the rapidjson GetObject gets translated to GetObjectA or GetObjectW everywhere. When you have "windows.h" in some places, then the trouble start. In my code I have to do some workaround to make sure I never include "windows.h" together with rapidjson. When I had that issue, I was surprised I couldn't find much about this online. I guess this must be a rather common problem.

All 7 comments

This is most likely because of the GetObject macro defined in the windows headers (in wingdi.h):

WINGDIAPI int   WINAPI GetObjectA(__in HANDLE h, __in int c, __out_bcount_opt(c) LPVOID pv);
WINGDIAPI int   WINAPI GetObjectW(__in HANDLE h, __in int c, __out_bcount_opt(c) LPVOID pv);
#ifdef UNICODE
#define GetObject  GetObjectW
#else
#define GetObject  GetObjectA
#endif // !UNICODE

Long time ago some genius at microsoft thought it was a good ideal to redefine the meaning of GetObject in the whole world. When "windows.h" is included systematically, there is no problem as the rapidjson GetObject gets translated to GetObjectA or GetObjectW everywhere. When you have "windows.h" in some places, then the trouble start. In my code I have to do some workaround to make sure I never include "windows.h" together with rapidjson. When I had that issue, I was surprised I couldn't find much about this online. I guess this must be a rather common problem.

I was able to work around this issue by adding the following after all includes:

#ifdef _MSC_VER
#undef GetObject
#endif

I faced now the same issue.
I'm including in my logger class and needed a log when parsing a json. Long story short, my build was full of errors generated by GetLogger()

My workaround is dubious at best: I reversed the order of the includes:

#include "Logger/Logger.h"       // ----> this includes windows.h
#include "rapidjson/document.h"

This is not ok, because I hardly fixed anything and it depends on inclusion order; not to mention I'm not 100% sure why it works.

Unfortunately for the moment it's not an option to remove Windows.h from the Logger.

I know folks are trying to make a point about the stupidity of windows.h. You're right.

However, stubborn is as stubborn does. All the authors of this library have to do is to rename their function to get_object

I won't change RapidJSON to another alternative just because some Microsoft stubborn developer wanted to show their elitist "great" ideas in their code... So wouldn't it be better to refactor all "Object" occurrences to something like "Obj" or something similar in the library? Adding includes just to fix an error from another human's fail makes -in my opinion- ugly and more-difficult-to-maintain code...

This error makes me sad, I hope you guys will fix it so that we don't have to sprinkle #undef ... all over our code.
I can see the open PR - kudos for trying to fix the problem, and it's a pity the PR hasn't been accepted.

If the problem is that renaming methods will break existing code, then I propose a compromise: instead of just renaming the methods, add conflict-free _alternative_ names. Move the implementation into the new alternative, and make old GetObject() and others call the new GetObj() or whatever name you see fit. That way old code won't notice a difference, and new code on Windows can use the new names and not have to undef stuff.

@VioletGiraffe is absolutely right. Her suggestion is both reasonable common sense & simple to implement.

If "GetObject" was some kind of awesome function name, one might feel bad about choosing another. However, it's not a good name at all. Too generic. How about GetJSON() or GetRapidJson() or just json(). Every instance in C++ is an object, so it doesn't add any information. It's likely using the word "class" in a class name: class EmployeeClass ...

Similarly "Get" is implied by having a return value. So, "GetObject" imparts ZERO information. May as well call it "foo"

Was this page helpful?
0 / 5 - 0 ratings

Related issues

frankw2 picture frankw2  路  3Comments

lixiaofan0 picture lixiaofan0  路  3Comments

leeyiw picture leeyiw  路  4Comments

Andy1978 picture Andy1978  路  3Comments

panovr picture panovr  路  4Comments