2

I have a Visual C++ Project in which I added the rapidjson library, which is tested to be working properly. But when I add a rapidjson::Document type to the nested class is throwing a LNK2019 error when I try to compile. The project is a dynamic library to create a DLL.

This are the definitions in my main.h:

class coreBD {
string conn;
string proxy;
int type;
Document test;

enum dataBases {
    Sqlite,
    SqlServer,
    None
};

string queryBD(string sSQL);
string queryHTTP(string sSQL);

string httpRequest(string url, string proxy);

static string getNow(string format);
static string urlEncode(string url);
static bool startsWith(string source, string with);

public:

enum access {
    dbConn,
    HTTPProtocol
};

//Nested class
class jsonObj {
    string jsonStr;
    string message;
    Document doc; //HERE IS THE PROBLEM
    bool validMsg;

public:
    enum response {
        FullResponse,
        SQLResponse
    };

    jsonObj(string json);
    string getJsonStr(response rType);
    string getErrorMsg();
    bool isValidResponse();
};

coreBD(string connStr, access connType);
jsonObj query(string sSQL);
void setProxy(string proxy);
};

This is the error:

error LNK1120: 1 unresolved externals

error LNK2019: unresolved external symbol "private: __thiscall rapidjson::GenericValue,class rapidjson::MemoryPoolAllocator >::GenericValue,class rapidjson::MemoryPoolAllocator >(class rapidjson::GenericValue,class rapidjson::MemoryPoolAllocator > const &)" (??0?$GenericValue@U?$UTF8@D@rapidjson@@V?$MemoryPoolAllocator@VCrtAllocator@rapidjson@@@2@@rapidjson@@AAE@ABV01@@Z) referenced in function "public: __thiscall rapidjson::GenericDocument,class rapidjson::MemoryPoolAllocator >::GenericDocument,class rapidjson::MemoryPoolAllocator >(class rapidjson::GenericDocument,class rapidjson::MemoryPoolAllocator > const &)" (??0?$GenericDocument@U?$UTF8@D@rapidjson@@V?$MemoryPoolAllocator@VCrtAllocator@rapidjson@@@2@@rapidjson@@QAE@ABV01@@Z)

The error disappears when I comment the line commented with HERE IS THE PROBLEM in the code. As you can see, the use of the test variable in the coreBD class causes no error. The mere existence of the variable of type rapidjson::Document in the nested class causes de error to show; it doesn't matter if I use it or not.

What could be the problem?


EDIT:

New information gathered.

The problem appears when I use the nested class inside the parent one, but only in the return of a method. In other words: I can create everything with rapidjson::Document type as a member variable, I can create a method in coreBD class with type jsonObj, I can instantiate jsonObj inside that methods, but I cannot return a value of type jsonObj if the class jsonObj has a rapidjson::Document member variable declared.

For example this new created method:

jsonObj coreBD::testOBJ()
{
    string json = "{error:null, message:None, errorMessage:MoreNone}";
    jsonObj b(json);
    return b; //It fails here if I return a nested class with a rapidjson::Document in it. Returning NULL works
}

EDIT:

New question continuing solving this: Perform a copy of Document object of rapidjson

Community
  • 1
  • 1
SysDragon
  • 9,692
  • 15
  • 60
  • 89
  • add rapidjason's library file as reference to your project properties. – Elixir Techne Mar 27 '14 at 08:58
  • @Trinity rapidjson are only headers, which are included in my project with `#include`s, and as you can read, the library is working properly in every other part of my project – SysDragon Mar 27 '14 at 08:59
  • Is this a separate solution by any chance? Meaning that other working parts of your application are placed in different solutions of your project. – XAMlMAX Mar 27 '14 at 09:06
  • @XAMlMAX Nope. One unique solution. I have a C++/CLI wrapper too, if that matters. And the project is a dynamic library. – SysDragon Mar 27 '14 at 09:07
  • Are you using this `rapidjson::Document` anywhere else in your project? I know you said it works everywhere else in the solution but does the `rapidjson::Document` works everywhere else as well? – XAMlMAX Mar 27 '14 at 09:10
  • @XAMlMAX Yes, it works. As you can see I even added the variable `Document test` in the main class and it causes no problem. It only fails on the nested class, and I can't find why. – SysDragon Mar 27 '14 at 09:12
  • My apologies :-) just read the code again and spotted it right at the top :-) – XAMlMAX Mar 27 '14 at 09:13
  • It looks to me like there is a problem with the copy or move code generated. The template is not generating a necessary copy or move constructor? – Richard Chambers Mar 27 '14 at 12:27
  • @RichardChambers No automatic code generated being used. No copy or move constructor defined on the classes. It is necessary to return the class object? – SysDragon Mar 27 '14 at 14:03
  • @SysDragon, the area of copy constructors and move constructors is a grey area for me as well especially for returning objects so I am afraid that I can not provide specific advice. It just looks to me like the compiler wants to use something from rapidjson that is not available. And I know that in order to prevent the use of copy or move or assignment for a particular class, the use of `private:` with method declarations in the class is used to wall off the use of those methods. – Richard Chambers Mar 27 '14 at 15:02
  • This article on object returning in C++ may provide a starting place http://www.bogotobogo.com/cplusplus/object_returning.php – Richard Chambers Mar 27 '14 at 15:09
  • @RichardChambers You were right. Seems like the problem is the copy of the `rapidjson::Document` objets. I'm making my own Copy Constructor and when I try to copy the `Document` elements it says that the operator= is inaccessible. Consider adding an answer with this information. – SysDragon Mar 27 '14 at 15:22

2 Answers2

1

Looking at the error it appears that the function returning the jsonObj is doing some kind of a copy or move construction as a part of returning the value and the underlying classes do not allow this probably by making those constructors private members.

There are classes whose design requires that a copy or assignment is prohibited in order to prevent memory leaks or because the objects are singleton type objects and only one version of the object is allowed.

Looking at this documentation on rapidjson there is a note in the section on Move semantics that may be pertinent. It looks like they are preventing a Copy in order to improve performance.

Richard Chambers
  • 16,643
  • 4
  • 81
  • 106
  • Looks like the part to the documentation relative to the `Document` object is missing. – SysDragon Mar 27 '14 at 16:16
  • @SysDragon, I think you are right, the documentation seems incomplete. However there is a section entitled Move Semantics about 2/3 of the way down from the top that discusses assignment, copy, and move. In general the documentation seems to be pretty skimpy. There is a comment in the document.h include file that copy constructor is not permitted see line 54 https://code.google.com/p/rapidjson/source/browse/trunk/include/rapidjson/document.h – Richard Chambers Mar 27 '14 at 18:03
  • That's the problem I'm having now. I can't define de copy constructor because "cannot access private member". I'm trying to use the `Document.Accept()` method, which seems to perform a copy: http://stackoverflow.com/a/19604013/1967056 – SysDragon Mar 28 '14 at 08:19
  • I think [I'm going to create a new question](http://stackoverflow.com/q/22707814/1967056) since this has gone to far and different to the original problem and is growing too much. Thanks for your help. See my edit. – SysDragon Mar 28 '14 at 08:45
0

jsonObj doesn't have copy constructor and it can't have any copy constructor since Document's copy constructor is disabled in rapidjson. Try to hold pointer to document instead, something like this :

class jsonObj {
    string jsonStr;
    string message;
    Document* doc; //HERE IS THE PROBLEM
    bool validMsg;
}

Or pass document(jsonObj) from outside to:

jsonObj query(string sSQL);

For example:

query(string sSQL, jsonObj & out_obj)
SysDragon
  • 9,692
  • 15
  • 60
  • 89
Roman
  • 21
  • 5