Hi,

I'm trying to use Agar from C++, and am having trouble getting event
callbacks,
like those initiated by AG_Button click events, to call a class method
properly.
The following 4 code files are my attempt at wrapping the Agar GUI elements,

using the Boost library to set up the C-style callback to a class method:

::::::::::::::
guiwin.h
::::::::::::::
#include <agar/core.h>
#include <agar/core/snprintf.h>
#include <agar/gui.h>

#include <boost/bind.hpp>
#include <boost/function.hpp>

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#ifndef GUIWIN_H
#define GUIWIN_H
class Guiwin {
    public:
        void init (void);
        void dump_content (void);

    private:
        AG_Window *win_;
        AG_Textbox *sltb_;

        typedef boost::function<void(AG_Event*)> AG_callback;
        static AG_callback click_callback;
        static void doClickDefFunc(AG_callback func) { click_callback =
func; }
        static void doClick(AG_Event *event) { click_callback(event); }
        void clickHandler(AG_Event *event);
};
#endif

::::::::::::::
guiwin.cpp
::::::::::::::
#include "guiwin.h"

// initialize static function pointer
Guiwin::AG_callback Guiwin::click_callback = 0;

void Guiwin::init (void) {
    // set up dynamic function pointer for event
    Guiwin::doClickDefFunc(boost::bind(&Guiwin::clickHandler, *this, _1));

    AG_Button *submit;
    win_ = AG_WindowNew(0);
    AG_WindowSetCaption(win_, "Single-line Example");

    sltb_ = AG_TextboxNew(win_, 0, "Static string: ");
    AG_TextboxSizeHint(sltb_, "XXXXXXXXXXX");
    AG_TextboxPrintf(sltb_, "Hello");
    AG_WidgetFocus(sltb_);

    submit = AG_ButtonNewFn(win_, 0, "Click me", doClick, NULL);

    AG_WindowSetPosition(win_, AG_WINDOW_MIDDLE_LEFT, 0);
    AG_WindowShow(win_);
}

void Guiwin::clickHandler (AG_Event *event) {
    // the AG_TextboxDupString() call generates a segmentation fault
    printf("text is: %s\n", AG_TextboxDupString(sltb_));
}

::::::::::::::
main.cpp
::::::::::::::
#include "guiwin.h"

int main(int argc, char *argv[]) {
    if (AG_InitCore("agar-textbox-demo", 0) == -1) {
        fprintf(stderr, "%s\n", AG_GetError());
        return (1);
    }
    if (AG_InitVideo(640, 480, 32, AG_VIDEO_RESIZABLE) == -1) {
        fprintf(stderr, "%s\n", AG_GetError());
        return (-1);
    }

    Guiwin testwin;
    testwin.init();

    AG_BindGlobalKey(SDLK_ESCAPE, KMOD_NONE, AG_Quit);

    AG_EventLoop();
    AG_Destroy();
    return (0);
}

::::::::::::::
Makefile
::::::::::::::
all:
    g++ -I/usr/include/agar -I/usr/include/SDL -I/usr/include/freetype2 \
        -lag_core -lag_gui -lSDL -lfreetype -ljpeg guiwin.cpp main.cpp \
        -o main.exe

I'm using Agar version 1.3.3 on an Ubuntu box with g++.  Compiles fine, but
when I click the button in the running program, I get a segfault.  The
corefile
gives me the following backtrace:

Core was generated by `./main.exe'.
Program terminated with signal 11, Segmentation fault.
[New process 21397]
#0  0x00000000004017ca in Guiwin::clickHandler ()
(gdb) bt
#0  0x00000000004017ca in Guiwin::clickHandler ()
#1  0x0000000000401f68 in boost::_mfi::mf1<void, Guiwin,
ag_event*>::operator() ()
#2  0x0000000000402011 in boost::_bi::list2<boost::_bi::value<Guiwin>,
boost::arg<1> (*)()>::operator()<boost::_mfi::mf1<void, Guiwin, ag_event*>,
boost::_bi::list1<ag_event*&> > ()
#3  0x0000000000402058 in boost::_bi::bind_t<void, boost::_mfi::mf1<void,
Guiwin, ag_event*>, boost::_bi::list2<boost::_bi::value<Guiwin>,
boost::arg<1> (*)()> >::operator()<ag_event*> ()
#4  0x0000000000402082 in
boost::detail::function::void_function_obj_invoker1<boost::_bi::bind_t<void,
boost::_mfi::mf1<void, Guiwin, ag_event*>,
boost::_bi::list2<boost::_bi::value<Guiwin>, boost::arg<1> (*)()> >, void,
ag_event*>::invoke ()
#5  0x0000000000402902 in boost::function1<void, ag_event*,
std::allocator<void> >::operator() ()
#6  0x0000000000402924 in Guiwin::doClick ()
#7  0x00007f072bbdfe12 in AG_PostEvent () from /usr/lib/libag_core.so.1
#8  0x00007f072b922d88 in mousebuttonup () from /usr/lib/libag_gui.so.1
#9  0x00007f072bbdfe12 in AG_PostEvent () from /usr/lib/libag_core.so.1
#10 0x00007f072b906a6d in AG_WidgetMouseButtonUp () from
/usr/lib/libag_gui.so.1
#11 0x00007f072b90a796 in AG_WindowEvent () from /usr/lib/libag_gui.so.1
#12 0x00007f072b902295 in AG_ProcessEvent () from /usr/lib/libag_gui.so.1
#13 0x00007f072b902015 in AG_EventLoop_FixedFPS () from
/usr/lib/libag_gui.so.1
#14 0x00000000004029e3 in main ()
Current language:  auto; currently asm
(gdb)

(Do I need to compile Boost with debugging symbols to get useful info
from this backtrace?)

I'm not super-experienced with C, C++, or Boost for that matter.  If anyone
could
spot how I'm doing this incorrectly, knows how to wrap Agar callbacks for
use in
C++, or could point me toward the right direction, it'd be greatly
appreciated.

Also, if there's any word on progress for the C++ wrapper classes for Agar,
I'd be
very interested to hear about it.

Thanks,

Ocamler
_______________________________________________
Agar mailing list
[email protected]
http://libagar.org/lists.html

Reply via email to