0

I'm trying to link against a dll that I have all the source for, but I can't get access to a dirt simple class I've created in it without getting LNK2019's.

I made this:

class makeprob
{
public:
    makeprob();
    ~makeprob();
};

with the implementation:

makeprob::makeprob() { }
makeprob::~makeprob() { }

as a nice simple template. Then in my actual project, I have the following:

#include "evil_dll.h"

class PC
{
public:
    PC() { };
    ~PC() { };

    static makeprob ProblemCreator;
};

with the implementation:

#include "evil_dll.h"

makeprob PC::ProblemCreator;

When I then try to link against it and construct a makeprob class, I get

LNK2019 unresolved external symbol "public: __thiscall makeprob::makeprob(void)" (??0makeprob@@QAE@XZ) referenced in function "void __cdecl `dynamic initializer for 'public: static class makeprob PC::ProblemCreator''(void)" (??__E?ProblemCreator@PC@@2Vmakeprob@@A@@YAXXZ)

I've checked that I'm linking against the lib and I am. From everything I can tell, the dll is a 32 bit dll to go with my 32 bit app. I am already using functions from the dll, but they've been declared with __declspec(dllimport)

I have to admit; I'm all thumbs with this. I have no idea if I'm supposed to do anything specific on the receiver to bring a class across from a dll. This is part of a school test, and part of the instructions tell me I don't need to edit the source code (just use the provided classes). I only created the makeprob class to make the problem simple to post up here.

Any advice would be invaluable! Thank you so much!

Tintelpe
  • 25
  • 4
  • This may be meaningless, just trying to add as much info as possible -- the library has a root namespace of "system" set in Visual Studio. I tried playing around with using the namespace, but didn't get anywhere. – Tintelpe Jul 23 '19 at 05:01
  • 1
    Are you aware that you have to `__declspec(dllexport)` classes and functions you want to export when you compile the DLL itself? To use a header in DLL as well as in another EXE (or DLL), a macro trickery is common like e.g. described here [SO: Static member variable not global between executable and dll](https://stackoverflow.com/a/50228234/7478597). (More can be found with [google "site:stackoverflow.com c++ declspec"](https://www.google.com/search?q=site%3Astackoverflow.com+c%2B%2B+declspec).) – Scheff's Cat Jul 23 '19 at 05:06
  • looks like you already have solution. There is a convention of exporting classes and functions from the dll hence the usage of dllimport/dllexport declarations, which is not followed in the code you showed. Please look at [this](https://learn.microsoft.com/en-us/cpp/cpp/using-dllimport-and-dllexport-in-cpp-classes?view=vs-2019) link. – dorKKnight Jul 23 '19 at 05:10
  • I'm not aware of this, but it sounds exciting! I do have such a macro (systemAPI) -- am I supposed to add something like this to the system_main.h: "systemAPI class makeprob;"? – Tintelpe Jul 23 '19 at 05:20
  • Exciting! This works, though not as I just described it. I'm going to write up a more formal answer, but Scheff deserves the credit here. Not sure how to give him credit on a comment? – Tintelpe Jul 23 '19 at 05:23

1 Answers1

0

Scheff actually answers this in the comments above, just formalizing it for Stack Overflow, but Scheff deserves all the cool-haircut-and-rayban-sunglasses points.

My problem is the class implementation doesn't export the constructor or destructor. My makeprob header file above should read like this:

class makeprob
{
public:
    __declspec(dllexport) makeprob();
    __declspec(dllexport) ~makeprob();
};

to have access to those. Scheff further suggests using macros for this (which I have found they already exist: systemAPI) instead of writing it out manually.

This doesn't get around my professor telling me I don't need to edit the source, but since all the other functions of the class I'm importing have systemAPI in front of them, and only the constructor and destructor don't, I'm gonna call it an oversight? Unless there is a fancy way to import a class without its constructor/destructor.

Thanks everyone!

Tintelpe
  • 25
  • 4
  • I left this up, but actually I've found it out was a trap! There was an extern global pointer to the class I needed. The constructor/destructor are intentionally hidden to force us to use the global. *shakes fist at scholastic system* – Tintelpe Jul 23 '19 at 05:51