nlohmann / json

JSON for Modern C++

Home Page:https://json.nlohmann.me

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Not working for classes containing "_declspec(dllimport)" in their declaration

shikhartanwar opened this issue · comments

Hi,

I have a 3rd party SDK included in my project that has class declarations like below -
Let's assume the class name as Person (simplified the code for reporting purposes) -

class _declspec(dllimport) Person 
{
       public std::string name;
}

I am trying to serialize the class using the below to_json function as mentioned in the documentation -

#include <Person.h>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
void to_json(json& j, Person & o)
{
	j = json{ { "value", o.name } };
}

Person p = new Person();
p.name = "Test";
json j = p;

However even though everything is syntactically correct, I am getting the below errors on building my project -

  1. could not find to_json() method in T's namespace
  2. 'force_msvc_stacktrace': is not a member of 'Person'
  3. 'force_msvc_stacktrace': undeclared identifier
  4. forcing MSVC stacktrace to show which T we're talking about.

I have also tried creating a simple class without the _declspec(dllimport) and that works like a charm.

Can someone please help in this regard?

Details:

  1. Compiler: Visual Studio 2017
  2. Operating System: Windows

Hello,

Assuming your code is not too different from what you reported, my first guess would be that the second argument of to_json must be a const reference.

void to_json(json&, Person const&){}

Did you put the const reference when trying with a different class? That would explain why it worked.

Nope using a const reference also does not make a difference. When I tried with my own class as compared to the class coming from the 3rd party SDK, I declared the to_json function as below -

void to_json(json& j, Person*  o);

No other definition was working for me. However, when I used the same logic for the class coming from the 3rd party SDK, it started throwing the errors that I mentioned in my previous comment

Is the type from the third party in a namespace?

Oh, wait I did miss the part about third party type...

Please take a look here, that should help solve your problem.

@theodelrieu I am not sure if the specified section helps me. I know for a fact that the 3rd party library does not contain boost::optional or std::filesystem::path namespaces.
Shouldn't the generic serializer work in that case?

@gregmarr Yes!

namespaces boost and std are merely examples in this section. The same reasoning apply to every third party namespace as well.

I know. But the 3rd party library does not use any custom namespace.

Instead, I am consuming it as a DLL that exposes its symbols using the __declspec(dllimport) specifier.

FYI, namespaces and dllexport are not mutually exclusive.

I'm confused. I asked if it uses a namespace, and you said yes to me, but then you said one message later that it doesn't use a namespace. That answer is VERY important. If the type is in a namespace, then the to_json function needs to be in the same namespace.

@gregmarr Sorry for the confusion but the third party type is not in a namespace. I read the documentation and was aware of the fact that the to_json function needs to be in the same namespace as that of the type. That's why I raised the bug as it is was not working for me.

Also, I am not sure as to how dllexport functions internally and what changes need to be done to make it work with this library because it was not working with the generic serializer.

Please let me know if you need any other details. I am more than willing to help in this matter and I'll make sure I do my due diligence.

Person p = new Person();
p.name = "Test";
json j = p;

This code can't be correct, as you are assigning a Person* to a Person, so it shouldn't even compile, and then if you fix that, you're assigning a Person* to json when you should be assigning a Person.

Just to make sure that we're looking at the right thing, can you post the exact test code and error message if possible?
If it works without dllimport but fails with it, then there's probably something weird that MSVC is doing.

Ok give me some time. I'll post similar/simplified code to demonstrate the workflow and the errors that i am encountering.

I would have to make a custom DLL project that exposes the functions in a similar manner, as the third party library that I am talking about has been developed inhouse. So, I can't really post the exact code here.

Hi guys,

I was able to get this work while I was building the sample application. Basically I was maintaining the to_json methods in a separate .hpp file and that file was not being included wherever the json j = p serializations were written. Because of this, the to_json methods were not discoverable. I was wrong in assuming that the methods would be discoverable in the global namespace.

Maybe we can cover this via documentation and be explicit about it so that no one else runs into this issue?

Anyways, thanks a lot for your prompt responses. Now I will go on and use this awesome library.

Alright, I shall add a note to the documentation.