Difference between revisions of "D-Bus examples"

From Apertium
Jump to navigation Jump to search
(Category:Documentation in English)
 
(18 intermediate revisions by 7 users not shown)
Line 14: Line 14:
   
 
mode_name = 'en-af'; # The name of the installed mode
 
mode_name = 'en-af'; # The name of the installed mode
dbus_mode_name = '/' + '_'.join(pair_name.split('-')); # Some mandatory mangling
 
   
 
bus = dbus.SessionBus(); # Create a new session bus
 
bus = dbus.SessionBus(); # Create a new session bus
   
  +
# Get the translator
translator = dbus.Interface(bus.get_object('org.apertium.mode', dbus_mode_name), 'org.apertium.Mode'); # Get the translator
 
  +
translator = dbus.Interface(bus.get_object('org.apertium.mode', '/'), 'org.apertium.Translate');
   
 
input = sys.stdin.read(); # Read the data
 
input = sys.stdin.read(); # Read the data
   
print translator.translate({}, input); # Print the translation
+
print translator.translate(mode_name, {}, input); # Print the translation
   
 
</pre>
 
</pre>
   
 
==Java==
 
==Java==
  +
{{see-also|Installing the Java D-Bus bindings|Compiling a Java D-Bus program}}
  +
{{Java_D-Bus_snippet}}
   
  +
In this program, we simply use the proxy object to invoke the <code>modes</code> method on the D-Bus object <code>org.apertium.info</code>. This returns a Java <code>List&lt;String&gt;</code>; we enumerate this list, printing each string.
===Installing the Java D-Bus bindings===
 
   
  +
==C++==
First you will need to [http://dbus.freedesktop.org/releases/dbus-java/dbus-java-2.3.2.tar.gz download the D-Bus bindings for Java]; the latest version can be found on the [http://www.freedesktop.org/wiki/Software/DBusBindings D-Bus project site]. The bindings use [http://www.matthew.ath.cx/projects/java/libmatthew-java-0.5.tar.gz libmatthew] by the same author; the latest version can be [http://www.matthew.ath.cx/projects/java/ downloaded from his site].
 
  +
{{see-also|Installing the C++ D-Bus bindings|Compiling a C++ D-Bus program}}
  +
{{C++_D-Bus_snippet}}
   
  +
This program is a simple emulation of the main apertium program. It takes a single parameter, which is the translation mode (something like en-ca). It reads words from stdin and calls the method <code>translate</code> on the D-Bus proxy object <code>translator</code> to translate the text read from stdin. When the translation is complete, it writes the translated string to stdout.
# Compile and install libmatthew.
 
# Compile and install the Java D-Bus bindings (ignore errors about invalid JAR paths - if it compiles and installs, everything will work.)
 
   
  +
==Clojure==
The Java binding build process should install the following binaries on your machine:
 
  +
<pre>
# CreateInterface
 
  +
(import '(org.freedesktop.dbus DBusConnection))
# DBusCall
 
# DBusDaemon
 
# DBusViewer
 
# ListDBus
 
   
  +
(def bus (. DBusConnection (getConnection (. DBusConnection SESSION))))
You can make sure that everything works by executing:
 
<pre>DBusCall org.apertium.info / org.apertium.Info modes</pre>
+
(def info (. bus (getRemoteObject "org.apertium.info" "/" (class org.apertium.Info))))
If you get a message such as
 
<pre>ParseException: Bus address is blank</pre>
 
it means that the environment variable $DBUS_SESSION_BUS_ADDRESS isn't set. You can get around it by using <code>dbus-launch --exit-with-session</code> to execute the program:
 
<pre>dbus-launch --exit-with-session DBusCall org.apertium.info / org.apertium.Info modes.</pre>
 
   
  +
(doseq mode (. info (modes))
You should get output that looks something like this:
 
  +
(prn mode))
<pre>[[en-af, af-en]]</pre>
 
   
  +
(. bus (disconnect))
=== Using D-Bus from Java ===
 
  +
</pre>
   
  +
[http://clojure.sourceforge.net/ Clojure] is a new Lisp dialect aimed at the Java Virtual Machine. You can see that the Clojure implementation is close to the Java implementation. To run the Clojure code, you will need to pass the same command line parameters to the Java Virtual Machine as for the Java example above.
Now that everything is working, it's time to create a Java program which uses an Apertium D-Bus object.
 
   
  +
== C - Glib Bindings ==
Since both D-Bus and Java use statically typed systems, Java needs to have the D-Bus interface descriptions of the objects it will use available at compile time. The 'CreateInterface' program in the Java D-Bus distribution creates Java interfaces by introspecting D-Bus objects.
 
 
We will create a Java interface corresponding to the info.apertium.Info interface and we will store it under the file org/apertium/Info.java. To do this, execute:
 
<pre>CreateInterface org.apertium.info / > org/apertium/Info.java</pre>
 
(and remember to use <code>dbus-launch --exit-with-session</code> if this does not work).
 
 
The contents out the newly created file should look something like:
 
 
<pre>
 
<pre>
  +
#include <glib.h>
/* File: org/apertium/Info.java */
 
  +
#include <glib-object.h>
package org.apertium;
 
  +
#include <dbus/dbus.h>
import java.util.List;
 
  +
#include <dbus/dbus-glib.h>
import org.freedesktop.dbus.DBusInterface;
 
public interface Info extends DBusInterface
 
{
 
   
  +
#define APERTIUM_SERVICE_NAME "org.apertium.mode"
public String directory();
 
  +
#define APERTIUM_INTERFACE "org.apertium.Translate"
public List<List<String>> get_pipeline(String mode);
 
  +
#define APERTIUM_OBJECT_PATH "/"
public List<String> get_filters(String _type);
 
public List<String> modes();
 
public String mode_directory();
 
   
  +
gboolean apertium_dbus_init();
}
 
  +
gboolean apertium_dbus_translate(const gchar*, gboolean, gchar*);
</pre>
 
   
  +
static DBusGConnection *conn = NULL;
The next step is to create our minimal Java program. Create a file called <code>TestDBus</code> with the following contents:
 
  +
static DBusGProxy *proxy = NULL;
<pre>
 
  +
static gchar *ceviri = NULL;
import org.freedesktop.DBus;
 
import org.freedesktop.dbus.DBusConnection;
 
import org.freedesktop.dbus.exceptions.DBusException;
 
   
  +
gboolean apertium_dbus_init()
import org.apertium.Info; // The interface we use to access org.apertium.info/
 
  +
{
  +
GError *error = NULL;
  +
  +
conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
  +
  +
if (conn == NULL) {
  +
g_warning("Error %s\n", error->message);
  +
g_error_free(error);
  +
return FALSE;
  +
}
  +
else
  +
{
  +
g_debug("conn object is %d\n", conn);
  +
}
   
  +
proxy = dbus_g_proxy_new_for_name_owner(conn,
class TestDBus {
 
  +
APERTIUM_SERVICE_NAME,
  +
APERTIUM_OBJECT_PATH,
  +
APERTIUM_INTERFACE,
  +
&error);
  +
  +
g_debug("proxy %d\n", proxy);
  +
  +
if (proxy == NULL || error != NULL)
  +
{
  +
g_warning("Cannot connect to the apertium service : %s\n", error->message);
  +
g_error_free(error);
  +
return FALSE;
  +
}
  +
else
  +
{
  +
return TRUE;
  +
}
  +
  +
}
   
  +
gboolean apertium_dbus_translate(const gchar* given_string, gboolean mark_unknown, gchar *translated_string)
public static void main(String[] args) throws org.freedesktop.dbus.exceptions.DBusException {
 
  +
{
DBusConnection bus = null;
 
  +
Info info = null;
 
  +
GError *error = NULL;
 
  +
gchar *ceviri = NULL;
bus = DBusConnection.getConnection(DBusConnection.SESSION);
 
  +
GHashTable *hash = NULL;
info = bus.getRemoteObject("org.apertium.info", "/", Info.class);
 
  +
gchar *option_key = "mark_unknown";
 
  +
gchar *option_value = NULL;
for (String s : info.modes()) {
 
  +
System.out.println(s);
 
  +
hash = g_hash_table_new(g_str_hash, g_str_equal);
}
 
  +
 
  +
if (mark_unknown)
bus.disconnect();
 
  +
{
  +
g_hash_table_insert(hash, "mark_unknown", "true");
  +
}
  +
else
  +
{
  +
g_hash_table_insert(hash, "mark_unknown", "false");
  +
}
  +
  +
dbus_g_proxy_call(proxy, "translate", &error,
  +
G_TYPE_STRING, "en-es",
  +
DBUS_TYPE_G_STRING_STRING_HASHTABLE, hash,
  +
G_TYPE_STRING, given_string,
  +
G_TYPE_INVALID,
  +
G_TYPE_STRING,
  +
&translated_string,
  +
G_TYPE_INVALID);
  +
  +
g_hash_table_destroy(hash);
  +
  +
if (error)
  +
{
  +
g_error_free(error);
  +
return FALSE;
  +
}
  +
else
  +
{
  +
g_error_free(error);
  +
return TRUE;
 
}
 
}
 
}
 
}
</pre>
 
   
To compile this program, we need to include the current path on the class path as well as the jar files needed by the Java D-Bus binding. To compile, execute (you should modify the directories to suit your installation):
 
<pre>
 
javac -cp .:/usr/local/share/java/dbus.jar:/usr/local/share/java/unix.jar:\
 
/usr/local/share/java/debug-disable.jar TestDBus.java
 
</pre>
 
   
  +
int main(int argc, char** argv)
To run the program, you need to specify the class paths specified above, as well as the JNI code (which installs to <code>/usr/local/lib/jni</code> by default (if you are using TCP instead of UNIX domain sockets for transport, then this won't be needed). You can run the program using:
 
  +
{
<pre>
 
  +
if (argc <= 1)
java -cp .:/usr/local/share/java/dbus.jar:\
 
  +
return 1;
/usr/local/share/java/unix.jar:/usr/local/share/java/debug-disable.jar\
 
  +
-Djava.library.path=/usr/local/lib/jni TestDBus
 
  +
g_type_init();
  +
  +
if (apertium_dbus_init() == FALSE)
  +
g_error("apertium_dbus_init, unable to connect apertium DBUS service");
  +
else
  +
{
  +
apertium_dbus_translate(argv[1], TRUE, ceviri);
  +
g_print("%s is : %s\n", argv[1], ceviri);
  +
g_free(ceviri);
  +
g_object_unref(proxy);
  +
}
  +
return 0;
  +
}
 
</pre>
 
</pre>
(and if it does not work, prefix the command with <code>dbus-launch --exit-with-session</code>).
 
 
Of course, if you are writing an application, you would hide all of these flags in a wrapper script.
 
   
 
[[Category:Development]]
 
[[Category:Development]]
  +
[[Category:Documentation in English]]

Latest revision as of 11:30, 24 March 2012

Here are some code snippets for various programming languages (complete with completely unnecessary comments) showing how you can interface with Apertium by means of D-Bus. You'll need to install the D-Bus service for Apertium.

Python[edit]

#!/usr/bin/python
# coding=utf-8
# -*- encoding: utf-8 -*-

import dbus, sys, codecs;

sys.stdin = codecs.getwriter('utf-8')(sys.stdin);
sys.stdout = codecs.getwriter('utf-8')(sys.stdout);

mode_name = 'en-af'; # The name of the installed mode

bus = dbus.SessionBus(); # Create a new session bus

# Get the translator
translator = dbus.Interface(bus.get_object('org.apertium.mode', '/'), 'org.apertium.Translate'); 

input = sys.stdin.read(); # Read the data

print translator.translate(mode_name, {}, input); # Print the translation

Java[edit]

See also: Installing the Java D-Bus bindings and Compiling a Java D-Bus program
import org.freedesktop.DBus;
import org.freedesktop.dbus.DBusConnection;
import org.freedesktop.dbus.exceptions.DBusException;

import org.apertium.Info; // The interface we use to access org.apertium.info/

class TestDBus {

        public static void main(String[] args) throws org.freedesktop.dbus.exceptions.DBusException {
                DBusConnection bus = null;
                Info info = null;

                bus = DBusConnection.getConnection(DBusConnection.SESSION);
                info = bus.getRemoteObject("org.apertium.info", "/", Info.class);

                for (String s : info.modes()) {
                        System.out.println(s);
                }

                bus.disconnect();
        }
}

In this program, we simply use the proxy object to invoke the modes method on the D-Bus object org.apertium.info. This returns a Java List<String>; we enumerate this list, printing each string.

C++[edit]

See also: Installing the C++ D-Bus bindings and Compiling a C++ D-Bus program
#include <map>
#include <iostream>
#include <sstream>
#include <string>

#include <dbus-c++/dbus.h>
#include "Translate-glue.h"

static const char* TRANSLATE_SERVICE_NAME = "org.apertium.mode";
static const char* TRANSLATE_OBJECT_PATH = "/";

class Translate
: public org::apertium::Translate,
  public DBus::IntrospectableProxy,
  public DBus::ObjectProxy
{
public:
    Translate(DBus::Connection& connection, const char* path, const char* name)
    : DBus::ObjectProxy(connection, path, name) {
    }
};

DBus::BusDispatcher dispatcher;

int main(int argc, char** argv) {
    DBus::default_dispatcher = &dispatcher;
    DBus::Connection bus = DBus::Connection::SessionBus();

    std::stringstream input;
    std::string mode;
    std::map< ::DBus::String, ::DBus::String> translate_options;

    if (argc != 2) {
        std::cerr << "usage: dbus_test <mode>" << std::endl;
        return 1;
    }

    mode = std::string(argv[1]);

    while (!std::cin.eof() and std::cin) {
        std::string str;
        std::cin >> str;
        input << str << " ";
    }

    Translate translator(bus, TRANSLATE_OBJECT_PATH, TRANSLATE_SERVICE_NAME);
    std::cout << translator.translate(mode, translate_options, input.str()) 
              << std::endl;
}

This program is a simple emulation of the main apertium program. It takes a single parameter, which is the translation mode (something like en-ca). It reads words from stdin and calls the method translate on the D-Bus proxy object translator to translate the text read from stdin. When the translation is complete, it writes the translated string to stdout.

Clojure[edit]

(import '(org.freedesktop.dbus DBusConnection))

(def bus (. DBusConnection (getConnection (. DBusConnection SESSION))))
(def info (. bus (getRemoteObject "org.apertium.info" "/" (class org.apertium.Info))))

(doseq mode (. info (modes))
       (prn mode))

(. bus (disconnect))

Clojure is a new Lisp dialect aimed at the Java Virtual Machine. You can see that the Clojure implementation is close to the Java implementation. To run the Clojure code, you will need to pass the same command line parameters to the Java Virtual Machine as for the Java example above.

C - Glib Bindings[edit]

#include 	<glib.h>
#include	<glib-object.h>
#include	<dbus/dbus.h>
#include	<dbus/dbus-glib.h>

#define 	APERTIUM_SERVICE_NAME   "org.apertium.mode"
#define 	APERTIUM_INTERFACE	"org.apertium.Translate"
#define 	APERTIUM_OBJECT_PATH	"/"

gboolean apertium_dbus_init();
gboolean apertium_dbus_translate(const gchar*, gboolean, gchar*);

static DBusGConnection *conn = NULL;
static DBusGProxy *proxy = NULL;
static gchar *ceviri = NULL;

gboolean apertium_dbus_init()
{
	GError *error = NULL;
	
	conn = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
	
	if (conn == NULL) {
		g_warning("Error %s\n", error->message);
                g_error_free(error);
		return FALSE;
	}
	else
	{
		g_debug("conn object is %d\n", conn);
	}

	proxy = dbus_g_proxy_new_for_name_owner(conn,
						APERTIUM_SERVICE_NAME,
						APERTIUM_OBJECT_PATH,
						APERTIUM_INTERFACE,
					        &error);
		
	g_debug("proxy %d\n", proxy);
									
	if (proxy == NULL || error != NULL)
	{
		g_warning("Cannot connect to the apertium service : %s\n", error->message);
		g_error_free(error);
		return FALSE;
	}
	else
	{
		return TRUE;
	}
	
}

gboolean apertium_dbus_translate(const gchar* given_string, gboolean mark_unknown, gchar *translated_string)
{
		
	GError *error = NULL;
	gchar *ceviri = NULL;
	GHashTable *hash = NULL;
	gchar *option_key = "mark_unknown";
	gchar *option_value = NULL;
	
	hash = g_hash_table_new(g_str_hash, g_str_equal);
	
	if (mark_unknown)
	{
		g_hash_table_insert(hash, "mark_unknown", "true");
	}
	else
	{
		g_hash_table_insert(hash, "mark_unknown", "false");
	}
	
	dbus_g_proxy_call(proxy, "translate", &error, 
					G_TYPE_STRING, "en-es", 
					DBUS_TYPE_G_STRING_STRING_HASHTABLE, hash, 
					G_TYPE_STRING, given_string,
					G_TYPE_INVALID,
					G_TYPE_STRING,
					&translated_string,
					G_TYPE_INVALID);
									
	g_hash_table_destroy(hash);
	
	if (error) 
        {
	    g_error_free(error);
            return FALSE;
        }
	else
        {
            g_error_free(error);
	    return TRUE;
        }
}


int main(int argc, char** argv)
{
	if (argc <= 1)
		return 1;
	
	g_type_init();	
	
	if (apertium_dbus_init() == FALSE)
		g_error("apertium_dbus_init, unable to connect apertium DBUS service");
	else
	{
		apertium_dbus_translate(argv[1], TRUE, ceviri);	
		g_print("%s is : %s\n", argv[1], ceviri);
		g_free(ceviri);
		g_object_unref(proxy);
	}	
	return 0;
}