Themabewertung:
  • 0 Bewertung(en) - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
libpurple unter Windows benutzen
#1
Sehr geehrte Freunde,

Ich möchte mir einen client für Windows XP programmieren unter verwendung der libpurple.dll. Als Entwicklungsumgebung verwende ich Dev-Cpp.
Dazu habe ich den Beipielcode von Libpurple.com genommen und die Implementierung der Eventloop Funktionen anhand von gtkeventloop.c an das Betriebssystem angepasst.
Ich habe folgende Libraries dem Compiler mitgeteilt

Code:
libpurple.dll.a
gtk/lib/glib-2.0.lib
Die libpurple.dll.a entstand dadurch, dass ich Pidgin aus dem sourcecode gemäß der Anleitung unter Windows kompiliert habe. Außerdem wurden folgende Include Verzeichnisse hinzugefügt:
libpurple  
gtk/include/glib-2.0  
gtk/lib/glib-2.0/include
gtk/lib/gtk-2.0/include
gtk/include/atk-1.0  
gtk/include/gtk-2.0
Außerdem wurde die libpurple.dll, die libglib-2.0-0.dll und die libxml2-2.dll ins Projektverzeichniss kopiert.
Im Folgenden der von mir abgeänderte Quellcode:
/*
* Sample libpurple program written by Michael C. Brook (http://libpurple.com/)
* (Some fragments taken from libpurple nullclient.c example found at http://pidgin.im/)
*/

#include "purple.h"

#include <glib.h>

#include <signal.h>
#include <string.h>
#include <unistd.h>

#include <stdio.h>

#define CUSTOM_USER_DIRECTORY  "/"
#define CUSTOM_PLUGIN_PATH     "/"
#define PLUGIN_SAVE_PREF       "/"
#define UI_ID                  "UI"

/**
* The following eventloop functions are used in both pidgin and purple-text. If your
* application uses glib mainloop, you can safely use this verbatim.
*/
#define PURPLE_GLIB_READ_COND  (G_IO_IN | G_IO_HUP | G_IO_ERR)
#define PURPLE_GLIB_WRITE_COND (G_IO_OUT | G_IO_HUP | G_IO_ERR | G_IO_NVAL)

typedef struct _PurpleGLibIOClosure {
    PurpleInputFunction function;
    guint result;
    gpointer data;
} PurpleGLibIOClosure;

typedef struct
{
    PurpleAccountRequestType type;
    PurpleAccount *account;
    void *ui_handle;
    char *user;
    gpointer userdata;
    PurpleAccountRequestAuthorizationCb auth_cb;
    PurpleAccountRequestAuthorizationCb deny_cb;
    guint ref;
} PurpleAccountRequestInfo;

static void purple_glib_io_destroy(gpointer data)
{
    g_free(data);
}

static gboolean purple_glib_io_invoke(GIOChannel *source, GIOCondition condition, gpointer data)
{
    PurpleGLibIOClosure *closure = data;
    PurpleInputCondition purple_cond = 0;

    if (condition & PURPLE_GLIB_READ_COND)
        purple_cond |= PURPLE_INPUT_READ;
    if (condition & PURPLE_GLIB_WRITE_COND)
        purple_cond |= PURPLE_INPUT_WRITE;


    if(! purple_cond) {
        return TRUE;
    }

    closure->function(closure->data, g_io_channel_unix_get_fd(source),
              purple_cond);

    return TRUE;
}

static guint glib_input_add(gint fd, PurpleInputCondition condition, PurpleInputFunction function,
                               gpointer data)
{
    PurpleGLibIOClosure *closure = g_new0(PurpleGLibIOClosure, 1);
    GIOChannel *channel;
    GIOCondition cond = 0;
    
    static int use_glib_io_channel = -1;

    if (use_glib_io_channel == -1)
        use_glib_io_channel = (g_getenv("PIDGIN_GLIB_IO_CHANNEL") != NULL) ? 1 : 0;
    
    closure->function = function;
    closure->data = data;

    if (use_glib_io_channel == 0)
        channel = (GIOChannel*) wpurple_g_io_channel_win32_new_socket(fd);
    else channel = g_io_channel_unix_new(fd);

    closure->result = g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond,
                          purple_glib_io_invoke, closure, g_free);

    g_io_channel_unref(channel);
    return closure->result;
}

static PurpleEventLoopUiOps glib_eventloops =
{
    g_timeout_add,
    g_source_remove,
    glib_input_add,
    g_source_remove,
    NULL,
#if GLIB_CHECK_VERSION(2,14,0)
    g_timeout_add_seconds,
#else
    NULL,
#endif

    /* padding */
    NULL,
    NULL,
    NULL
};
/*** End of the eventloop functions. ***/


static void network_disconnected(void)
{

    printf("This machine has been disconnected from the internet\n");

}

static void report_disconnect_reason(PurpleConnection *gc, PurpleConnectionError reason, const char *text)
{

    PurpleAccount *account = purple_connection_get_account(gc);
    printf("Connection disconnected: \"%s\" (%s)\n  >Error: %d\n  >Reason: %s\n", purple_account_get_username(account), purple_account_get_protocol_id(account), reason, text);

}

static PurpleConnectionUiOps connection_uiops =
{
    NULL,                      /* connect_progress         */
    NULL,                      /* connected                */
    NULL,                      /* disconnected             */
    NULL,                      /* notice                   */
    NULL,                      /* report_disconnect        */
    NULL,                      /* network_connected        */
    network_disconnected,      /* network_disconnected     */
    report_disconnect_reason,  /* report_disconnect_reason */
    NULL,
    NULL,
    NULL
};

static void ui_init(void)
{
    /**
     * This should initialize the UI components for all the modules.
     */

    purple_connections_set_ui_ops(&connection_uiops);

}

static PurpleCoreUiOps core_uiops =
{
    NULL,
    NULL,
    ui_init,
    NULL,

    /* padding */
    NULL,
    NULL,
    NULL,
    NULL
};

static void init_libpurple(void)
{
    /* Set a custom user directory (optional) */
    purple_util_set_user_dir(CUSTOM_USER_DIRECTORY);

    /* We do not want any debugging for now to keep the noise to a minimum. */
    purple_debug_set_enabled(FALSE);

    /* Set the core-uiops, which is used to
     *     - initialize the ui specific preferences.
     *     - initialize the debug ui.
     *     - initialize the ui components for all the modules.
     *     - uninitialize the ui components for all the modules when the core terminates.
     */
    purple_core_set_ui_ops(&core_uiops);

    /* Set the uiops for the eventloop. If your client is glib-based, you can safely
     * copy this verbatim. */
    purple_eventloop_set_ui_ops(&glib_eventloops);

    /* Set path to search for plugins. The core (libpurple) takes care of loading the
     * core-plugins, which includes the protocol-plugins. So it is not essential to add
     * any path here, but it might be desired, especially for ui-specific plugins. */
    purple_plugins_add_search_path(CUSTOM_PLUGIN_PATH);

    /* Now that all the essential stuff has been set, let's try to init the core. It's
     * necessary to provide a non-NULL name for the current ui to the core. This name
     * is used by stuff that depends on this ui, for example the ui-specific plugins. */
    if (!purple_core_init(UI_ID)) {
        /* Initializing the core failed. Terminate. */
        fprintf(stderr,
                "libpurple initialization failed. Dumping core.\n"
                "Please report this!\n");
        abort();
    }

    /* Create and load the buddylist. */
    purple_set_blist(purple_blist_new());
    purple_blist_load();

    /* Load the preferences. */
    purple_prefs_load();

    /* Load the desired plugins. The client should save the list of loaded plugins in
     * the preferences using purple_plugins_save_loaded(PLUGIN_SAVE_PREF) */
    purple_plugins_load_saved(PLUGIN_SAVE_PREF);

    /* Load the pounces. */
    purple_pounces_load();
}

static void signed_on(PurpleConnection *gc)
{
    PurpleAccount *account = purple_connection_get_account(gc);
    printf("Account connected: \"%s\" (%s)\n", purple_account_get_username(account), purple_account_get_protocol_id(account));
}

static void buddy_signed_on(PurpleBuddy *buddy)
{
    printf("Buddy \"%s\" (%s) signed on\n", purple_buddy_get_name(buddy), purple_account_get_protocol_id(purple_buddy_get_account(buddy)));
}

static void buddy_signed_off(PurpleBuddy *buddy)
{
    printf("Buddy \"%s\" (%s) signed off\n", purple_buddy_get_name(buddy), purple_account_get_protocol_id(purple_buddy_get_account(buddy)));
}

static void buddy_away(PurpleBuddy *buddy, PurpleStatus *old_status, PurpleStatus *status)
{
    printf("Buddy \"%s\" (%s) changed status to %s\n", purple_buddy_get_name(buddy), purple_account_get_protocol_id(purple_buddy_get_account(buddy)), purple_status_get_id(status));
}

static void buddy_idle(PurpleBuddy *buddy, gboolean old_idle, gboolean idle)
{
    printf("Buddy \"%s\" (%s) changed idle state to %s\n", purple_buddy_get_name(buddy), purple_account_get_protocol_id(purple_buddy_get_account(buddy)), (idle) ? "idle" : "not idle");
}

static void received_im_msg(PurpleAccount *account, char *sender, char *message, PurpleConversation *conv, PurpleMessageFlags flags)
{

    if (conv==NULL)
      {
      conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sender);
      }

    printf("(%s) %s (%s): %s\n", purple_utf8_strftime("%H:%M:%S", NULL), sender, purple_conversation_get_name(conv), message);

}

static void buddy_typing(PurpleAccount *account, const char *name)
{
    printf("User \"%s\" (%s) is typing...\n", name, purple_account_get_protocol_id(account));
}

static void buddy_typed(PurpleAccount *account, const char *name) //not supported on all protocols
{
    printf("User \"%s\" (%s) has typed something...\n", name, purple_account_get_protocol_id(account));
}

static void buddy_typing_stopped(PurpleAccount *account, const char *name)
{
    printf("User \"%s\" (%s) has stopped typing...\n", name, purple_account_get_protocol_id(account));
}

static int account_authorization_requested(PurpleAccount *account, const char *user)
{
    printf("User \"%s\" (%s) has sent a buddy request\n", user, purple_account_get_protocol_id(account));
    return 1; //authorize buddy request automatically (-1 denies it)
}

static void connect_to_signals(void)
{

    static int handle;

    purple_signal_connect(purple_connections_get_handle(), "signed-on", &handle,
                PURPLE_CALLBACK(signed_on), NULL);

    purple_signal_connect(purple_blist_get_handle(), "buddy-signed-on", &handle,
                PURPLE_CALLBACK(buddy_signed_on), NULL);

    purple_signal_connect(purple_blist_get_handle(), "buddy-signed-off", &handle,
                PURPLE_CALLBACK(buddy_signed_off), NULL);

    purple_signal_connect(purple_blist_get_handle(), "buddy-status-changed", &handle,
                PURPLE_CALLBACK(buddy_away), NULL);

    purple_signal_connect(purple_blist_get_handle(), "buddy-idle-changed", &handle,
                PURPLE_CALLBACK(buddy_idle), NULL);

    purple_signal_connect(purple_conversations_get_handle(), "received-im-msg", &handle,
                PURPLE_CALLBACK(received_im_msg), NULL);

    purple_signal_connect(purple_conversations_get_handle(), "buddy-typing", &handle,
                PURPLE_CALLBACK(buddy_typing), NULL);

    purple_signal_connect(purple_conversations_get_handle(), "buddy-typed", &handle,
                PURPLE_CALLBACK(buddy_typed), NULL);

    purple_signal_connect(purple_conversations_get_handle(), "buddy-typing-stopped", &handle,
                PURPLE_CALLBACK(buddy_typing_stopped), NULL);

    purple_signal_connect(purple_accounts_get_handle(), "account-authorization-requested", &handle,
                PURPLE_CALLBACK(account_authorization_requested), NULL);

}

int main(int argc, char *argv[])
{

    GMainLoop *loop = g_main_loop_new(NULL, FALSE);

    /* libpurple's built-in DNS resolution forks processes to perform
     * blocking lookups without blocking the main process.  It does not
     * handle SIGCHLD itself, so if the UI does not you quickly get an army
     * of zombie subprocesses marching around.
     */
    signal(1, SIG_IGN);

    init_libpurple();

    printf("libpurple initialized. Running version %s.\n", purple_core_get_version()); //I like to see the version number

    connect_to_signals();

    PurpleAccount *account = purple_account_new("UI", "prpl-icq"); //this could be prpl-aim, prpl-yahoo, prpl-msn, prpl-icq, etc.
    purple_account_set_password(account, "Passwort");

    purple_accounts_add(account);
    purple_account_set_enabled(account, UI_ID, TRUE);

    g_main_loop_run(loop);

    return 0;

}
Das Programm kompilierte Fehlerfrei. Als ich es ausführte erschien folgende Bildschirmausgabe:
libpurple initialized. Running version 2.7.11.

** (client.exe:804): CRITICAL **: purple_presence_is_online: assertion `presence
!= NULL' failed

Die Fehlermeldung wurde von der Funktion purple_account_set_enabled(account, UI_ID, TRUE); ausgelöst.
Es wurden keine Signale empfangen und der Kontakt war nicht online. Das gleiche Programm, bis auf meine Abänderungen bei den Eventloop Funktionen, funktionierte unter Ubuntu einwandfrei.
Meine Frage lautet, ob mein Vorgehen prinzipiell richtig ist um einen Client unter Windows mit der libpurple.dll zu programmieren und, falls es so möglich ist, was ich bei meinem Programm ändern muss, dass es unter Windows funktioniert. Natürlich würde mir ein unter Windows funktionierendes Beispielprogramm, welches libpurple.dll verwendet, sehr weiterhelfen.
Ich bedanke mich schon im Voraus für ihre Hilfe.

*Edit: geändert von Dirtsa und den Code als Code markiert. Bitte nächstes Mal selber als Code einfügen. Danke
Zitieren


Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste