Sign in to follow this  
Followers 0
cppman

Creating a wrapper around std::vector

7 posts in this topic

Hello,

I am having some trouble with writing a wrapper around the std::vector class. This class is used as a public member variable of another class, and it isn't exported to a DLL. Whenever I try to access it within the other class, the entire program stalls. If I access it from outside of the class, it works just fine. Here is the wrapper class:

typedef bool(*LPEVENT)(EventArgs);
 
     class EventList
     {
     public:
         EventList() { };
         ~EventList() { };
 
         void Add(LPEVENT value) 
         { 
             EventCallbacks.push_back(value); 
         }
 
         void Remove(LPEVENT value) 
         { 
             for (int i = 0; i < EventCallbacks.size(); i++) 
             {
                 if (EventCallbacks[i] == value) 
                 {
                     EventCallbacks.erase(EventCallbacks.begin() + i);
                     return;
                 }
             }
         }
 
         void operator+=(LPEVENT value)
         {
             Add(value);
         }
 
         void operator-=(LPEVENT value)
         {
             Remove(value);
         }
 
         int size() 
         { 
             return EventCallbacks.size(); 
         }
 
         LPEVENT operator[](int index) 
         { 
             return EventCallbacks[index]; 
         }
     private:
         std::vector<LPEVENT> EventCallbacks;
     };

and here is the class that uses it:

class Window : public Control /* Control is a pure virtual class with only 1 method (DefWndProc) */
     {
     public:
         virtual bool DefWndProc(MSG msg)
         {
             /* more code here.. removed for space -> has nothing to do with the problem. */
             return false;
         }
 
     public:
         EventList OnClose;
     };

Now, whenever I try to access the "OnClose" variable, the program stalls. Below is the code I am using to access it:

Window *wnd = MakeWindow("hello world", CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, WS_OVERLAPPEDWINDOW);
 std::cout << "test\n"; // this IS PRINTED to the screen.
 wnd->OnClose += windowClosed; // here is where it stalls..
 std::cout << "test\n"; // this is never printed to the screen.

However, when I use the following code, it doesn't stall:

EventList myList;
 myList += windowClosed;

Any ideas on what the problem is? I would really appreciated any input. Thanks.

Share this post


Link to post
Share on other sites



Is wnd valid? Are you sure your overloaded operator+=() is even being called? Try calling Add() directly instead of using it to see if the same thing happens. Insert more std::cout statements to further narrow down exactly what's being called and where it's stopping.

Also, an unrelated, you can remove most of your Remove() code by just using the remove_if function.

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

Is wnd valid? Are you sure your overloaded operator+=() is even being called? Try calling Add() directly instead of using it to see if the same thing happens. Insert more std::cout statements to further narrow down exactly what's being called and where it's stopping.

Also, an unrelated, you can remove most of your Remove() code by just using the remove_if function.

wnd is valid (non-null if that is what you are referring to). Yeah, the += operator works perfectly fine. Calling Add() directly has the same effect as using the += operator. I also made EventCallbacks public and accessed that directly, and that is where it is stalling. So, I am clueless as to why it would stall. (I really don't feel like implementing a linked list...)

And thanks. I didn't know about the remove* function.

* remove removes based on the value. remove_if removes based on a boolean predicate.

edit:

I set the warn level to /W4 (most strict), and I don't get any relevant warnings. The only warning I do get is about strcpy being unsafe.

Edited by cppman

Share this post


Link to post
Share on other sites

I added in the missing stuff:

struct EventArgs
{
};

bool windowClosed(EventArgs)
{
    return true;
}

And the code works for me.

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

Ok, weird. It also works for me when I remove MakeWindow(...). I think it is because that function is exported to a dll, however, the vector associated with the class is templated. I'll try putting the source in the header and see what happens.

edit:

Yep. MakeWindow allocates a Window object which has a vector as a public member variable. I'm assuming that it doesn't work because it doesn't know how to allocate that object within an unknown type?

Well, either way, that seemed to be the problem. Thanks for your help.

Edited by cppman

Share this post


Link to post
Share on other sites

There are issues with construction/destruction across DLL boundaries. The short of it is, unless you're careful with linker settings, there's no guarantee that operator new and operator delete will be compatible when one is in and the other is out of a DLL. You can fiddle with settings to get them the same, but then that introduces hard to find bugs the moment you use the DLL somewhere else with non-matching operators. It's best to handle all construction/destruction pairs inside the same module to avoid these issues.

Share this post


Link to post
Share on other sites

Ah, I see. With what you said, I just decided to just take a pointer to an all ready allocated Window object (and they can delete it themselves). It makes it much cleaner anyways. Thanks again. :)

Window wnd;
MakeWindow(&wnd, "hello world");

or

Window *wnd = new Window();
MakeWindow(wnd, "hello world");

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0