Fire Lancer
Fire Lancer

Reputation: 30135

C++ DLL: Not exposing the entire class

How can I "hide" parts of a class so that whoever is using the libary does not have to include headers for all the types used in my class. Ie take the MainWindow class below, ho can I have it so when compiled in a static/dynamic libary, whoever is useing the libary does NOT have to include windows.h, ie HWND, CRITICAL_SECTION, LRESULT, etc do not have to be defined.

I know I could split it into two classes, an abstract class with just the public interface, and an implementation class which is hidden that contains the members that require windows.h.

The problem here is that the visible class can no longer be created itsself, and an additional create function (eg CreateMainWindow) is required. That is fine in this case since it is most likly that just a single instance created on the heap is wanted but for other classes this is not.

class MainWindow
{
    HWND hwnd;
    int width, height;
    std::string caption;
    bool started,exited;
    bool closeRequest;

    unsigned loopThread;
    CRITICAL_SECTION inputLock;

    Input *input;
public:
    static void init_type();
    Py::Object getattr(const char *name);

    MainWindow(int width, int height, std::string caption);
    ~MainWindow();

    bool CloseRequest(const Py::Tuple &args);
    bool CloseRequestReset(const Py::Tuple &args);

    HWND GetHwnd();

    int GetWidth();
    int GetHeight();

    Input* GetInput();
protected:
    unsigned static __stdcall loopThreadWrap(void *arg);
    unsigned LoopThreadMain();

    LRESULT WndProc(UINT msg, WPARAM wParam, LPARAM lParam);
    LRESULT static CALLBACK WndProcWrapper(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
};

Upvotes: 0

Views: 646

Answers (5)

Rob K
Rob K

Reputation: 8926

As has been said before, you want to use a pimpl. I've done it and it works really well. It's totally transparent to the user of your library.

Upvotes: 0

user3458
user3458

Reputation:

One way or the other, you have two options:

  1. let the library user's compiler figure out the memory size needed for your data - then the compiler can place it on stack
  2. or allocate the data on the heap for the library user so that the user's compiler does not need to know how big the data are.

Whether you expose (2) via pimpl or MyAbstractObject *o = createMyObject() is not much different.

A third option (a hack so terrible, it's funny) creates a large byte array in the object you expose to the user, and you initialize your real objects in that array using "in-place" new. Please don't do this. I'll go and wash my brains with soap.

Upvotes: 1

ChrisW
ChrisW

Reputation: 56113

You can hide parts of a class using the so-called "cheshire cat", "letter/envelope", or "pimpl" technique (which are, all, different names for the same technique):

class MainWindow
{
private:
    //opaque data
    class ImplementationDetails;
    ImplementationDetails* m_data;
public:
    ... declare your public methods here ...
}

The best way is probably the abstract class mentioned in your 2nd paragraph (however I failed to understand your last sentence, in which you (tried/failed to) explain what your counter-argument to that is).

Upvotes: 7

Ateş Göral
Ateş Göral

Reputation: 140050

As you mentioned in your question, using an abstract interface is your best option. Your DLL should have factory methods for creating/destroying instances of your concrete class. I didn't quite get your point about the downside of this.

Upvotes: 4

Otávio Décio
Otávio Décio

Reputation: 74250

This book may give you some ideas:

http://www.amazon.com/Large-Scale-Software-Addison-Wesley-Professional-Computing/dp/0201633620

Large-Scale C++ Software Design

by John Lakos

Upvotes: 0

Related Questions