You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@subversion.apache.org by Morten Ludvigsen <mo...@yahoo.co.uk> on 2002/10/16 12:38:09 UTC
SWIG Java bindings
Is anyone actively working on SWIG-Java bindings?
If not I think I will take a crack at it :-)
Regards,
Morten Ludvigsen
2-People Software
Denmark
__________________________________________________
Do You Yahoo!?
Everything you'll ever need on one web page
from News and Sport to Email and Music Charts
http://uk.my.yahoo.com
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: SV: SWIG Java bindings
Posted by Greg Stein <gs...@lyra.org>.
On Thu, Oct 17, 2002 at 05:22:44PM -0700, Daniel Rall wrote:
> Greg Stein <gs...@lyra.org> writes:
>
> > I've been on Dan's case for this for a while -- to get him to send in a
> > patch, or even better: to provide commit access so that he can work on them
> > directly within the SVN repository.
>
> I guess commit access to the SWIG stuff would be good. Note that I
> have the same worries about breaking that trunk that Morten
> expressed. :)
Could each of you send a username/password to me (offlist :-), and I'll get
you added. (sorry for the delay)
Have no fear about operating within the trunk. How can you break the Java
bindings? They don't exist yet :-)
Feasably, you could break the Python ones thru a bad change to a .i file,
but please don't worry about that. I seriously doubt that will happen, but
if so... this *is* version control. We can always back a change out.
Cheers,
-g
--
Greg Stein, http://www.lyra.org/
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: SV: SWIG Java bindings
Posted by Daniel Rall <dl...@finemaltcoding.com>.
Greg Stein <gs...@lyra.org> writes:
> I've been on Dan's case for this for a while -- to get him to send in a
> patch, or even better: to provide commit access so that he can work on them
> directly within the SVN repository.
I guess commit access to the SWIG stuff would be good. Note that I
have the same worries about breaking that trunk that Morten
expressed. :)
--
Daniel Rall <dl...@finemaltcoding.com>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: SV: SWIG Java bindings
Posted by Morten Ludvigsen <mo...@yahoo.co.uk>.
--- Greg Stein <gs...@lyra.org> wrote:
> I've been on Dan's case for this for a while -- to get him to send in a
> patch, or even better: to provide commit access so that he can work on them
> directly within the SVN repository.
>
> Morten: I'd be more than happy to extend the same: if you want to work on
> the SWIG Java bindings, then we can get you commit access so you can work on
> them cooperatively with others.
[SNIP]
I think that could be a good idea. However I am not nearly confidant enough to
commit to the trunk so maybe we could have a branch for this work?
BTW. I just realised that I have not introduced myself. I will send an introduction
to the list this evening (Danish time).
Regards,
Morten Ludvigsen
2-People Software
Denmark
__________________________________________________
Do You Yahoo!?
Everything you'll ever need on one web page
from News and Sport to Email and Music Charts
http://uk.my.yahoo.com
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: SV: SWIG Java bindings
Posted by Greg Stein <gs...@lyra.org>.
I've been on Dan's case for this for a while -- to get him to send in a
patch, or even better: to provide commit access so that he can work on them
directly within the SVN repository.
Morten: I'd be more than happy to extend the same: if you want to work on
the SWIG Java bindings, then we can get you commit access so you can work on
them cooperatively with others.
Cheers,
-g
On Wed, Oct 16, 2002 at 06:52:20PM +0200, Morten Ludvigsen wrote:
> Thanks,
>
> I'll start looking at it now.
>
> Regards,
>
> Morten Ludvigsen
> 2-People Software
> Denmark
>
> > -----Oprindelig meddelelse-----
> > Fra: dlr@finemaltcoding.com [mailto:dlr@finemaltcoding.com]
> > Sendt: 16. oktober 2002 18:17
> > Til: Morten Ludvigsen; dev@subversion.tigris.org
> > Emne: Re: SWIG Java bindings
> >
> > Morten Ludvigsen <mo...@yahoo.co.uk> writes:
> >
> > > Is anyone actively working on SWIG-Java bindings?
> > >
> > > If not I think I will take a crack at it :-)
> >
> > Hi Morten. I've done a small amount of work on them. What I have is
> > swigging successfully, but may not compile (haven't tried yet) and
> > surely won't run (a lot of it is still incomplete/stubbed/broken). I
> > hope it's a useful starting place for you, and am very interested in
> > seeing some diffs with what ever progress you find time to make.
> > Hopefully I'll have time to help out a little more as well.
> > --
> >
> > Daniel Rall <dl...@finemaltcoding.com>
--
Greg Stein, http://www.lyra.org/
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
SV: SWIG Java bindings
Posted by Morten Ludvigsen <mo...@2ps.dk>.
Thanks,
I'll start looking at it now.
Regards,
Morten Ludvigsen
2-People Software
Denmark
> -----Oprindelig meddelelse-----
> Fra: dlr@finemaltcoding.com [mailto:dlr@finemaltcoding.com]
> Sendt: 16. oktober 2002 18:17
> Til: Morten Ludvigsen; dev@subversion.tigris.org
> Emne: Re: SWIG Java bindings
>
>
> Morten Ludvigsen <mo...@yahoo.co.uk> writes:
>
> > Is anyone actively working on SWIG-Java bindings?
> >
> > If not I think I will take a crack at it :-)
>
> Hi Morten. I've done a small amount of work on them. What I have is
> swigging successfully, but may not compile (haven't tried yet) and
> surely won't run (a lot of it is still incomplete/stubbed/broken). I
> hope it's a useful starting place for you, and am very interested in
> seeing some diffs with what ever progress you find time to make.
> Hopefully I'll have time to help out a little more as well.
> --
>
> Daniel Rall <dl...@finemaltcoding.com>
>
>
>
> Index: ./svn_types.i
> ===================================================================
> --- ./svn_types.i
> +++ ./svn_types.i Wed Oct 16 09:01:38 2002
> @@ -83,6 +83,9 @@
> $1 = PyString_AS_STRING($input);
> $2 = PyString_GET_SIZE($input);
> }
> +%typemap(java, in) (const char *PTR, apr_size_t LEN) {
> + /* FIXME: This is just a stub -- implement JNI code! */
> +}
>
> /*
> -----------------------------------------------------------------------
> Define a generic arginit mapping for pools.
> Index: ./svn_string.i
> ===================================================================
> --- ./svn_string.i
> +++ ./svn_string.i Wed Oct 16 09:01:03 2002
> @@ -42,6 +42,10 @@
> }
> $result = t_output_helper($result, s);
> }
> +%typemap(java,argout,fragment="t_output_helper") RET_STRING {
> + /* FIXME: This is just a stub -- implement JNI code! */
> + return NULL;
> +}
>
> /*
> -----------------------------------------------------------------------
> TYPE: svn_stringbuf_t
> @@ -137,5 +141,8 @@
> if ($1 == NULL)
> return NULL;
> }
> +%typemap(java,in) const apr_array_header_t *STRINGLIST {
> + /* FIXME: This is just a stub -- implement JNI code! */
> +}
>
> /*
> ----------------------------------------------------------------------- */
> Index: ./svn_fs.i
> ===================================================================
> --- ./svn_fs.i
> +++ ./svn_fs.i Fri Oct 11 19:46:41 2002
> @@ -113,4 +113,8 @@
> #ifdef SWIGPYTHON
> #include "swigutil_py.h"
> #endif
> +
> +#ifdef SWIGJAVA
> +#include "swigutil_java.h"
> +#endif
> %}
> Index: ./swigutil_java.c
> ===================================================================
> --- ./swigutil_java.c
> +++ ./swigutil_java.c Fri Oct 11 19:24:04 2002
> @@ -0,0 +1,602 @@
> +/*
> + * swigutil_java.c: utility functions for the SWIG Java bindings
> + *
> + * ====================================================================
> + * Copyright (c) 2000-2002 CollabNet. All rights reserved.
> + *
> + * This software is licensed as described in the file COPYING, which
> + * you should have received as part of this distribution. The terms
> + * are also available at http://subversion.tigris.org/license-1.html.
> + * If newer versions of this license are posted there, you may use a
> + * newer version instead, at your option.
> + *
> + * This software consists of voluntary contributions made by many
> + * individuals. For exact contribution history, see the revision
> + * history and logs, available at http://subversion.tigris.org/.
> + * ====================================================================
> + */
> +
> +
> +#include <jni.h>
> +
> +#include <apr_pools.h>
> +#include <apr_hash.h>
> +
> +#include "svn_string.h"
> +#include "svn_delta.h"
> +
> +#include "swigutil_java.h"
> +
> +
> +/* this baton is used for the editor, directory, and file batons. */
> +typedef struct {
> + jobject editor; /* the editor handling the callbacks */
> + jobject baton; /* the dir/file baton (or NULL for edit baton) */
> + apr_pool_t *pool; /* pool to use for errors */
> +} item_baton;
> +
> +typedef struct {
> + jobject handler; /* the window handler (a callable) */
> + apr_pool_t *pool; /* a pool for constructing errors */
> +} handler_baton;
> +
> +
> +static jobject make_pointer(const char *typename, void *ptr)
> +{
> + /* ### cache the swig_type_info at some point? */
> + return SWIG_NewPointerObj(ptr, SWIG_TypeQuery(typename), 0);
> +}
> +
> +/* for use by the "O&" format specifier */
> +static jobject make_ob_pool(void *ptr)
> +{
> + return make_pointer("apr_pool_t *", ptr);
> +}
> +
> +/* for use by the "O&" format specifier */
> +static jobject make_ob_window(void *ptr)
> +{
> + return make_pointer("svn_txdelta_window_t *", ptr);
> +}
> +
> +static jobject convert_hash(apr_hash_t *hash,
> + jobject (*converter_func)(void *value,
> + void *ctx),
> + void *ctx)
> +{
> + apr_hash_index_t *hi;
> + jclass cls = JCALL1(FindClass, jenv, "java/util/HashMap");
> + jobject dict = JCALL3(NewObject, jenv, cls,
> + JCALL3(GetMethodID, jenv, cls, "<init>", "(I)V"),
> + (jint) apr_hash_count(hash));
> + jmethoID put = JCALL3(GetMethodID, jenv, cls, "put",
> + "(Ljava/lang/Object;Ljava/lang/Object;)"
> + "Ljava/lang/Object;"),
> +
> + if (dict == NULL)
> + return NULL;
> +
> + for (hi = apr_hash_first(NULL, hash); hi; hi = apr_hash_next(hi))
> + {
> + const void *key;
> + void *val;
> + jobject value;
> +
> + apr_hash_this(hi, &key, NULL, &val);
> + value = (*converter_func)(val, ctx);
> + JCALL3(CallObjectMethod, jenv, put,
> + JCALL2(NewString, jenv, key, strlen(key)), value);
> + JCALL1(DeleteLocalRef, jenv, value);
> + }
> +
> + return dict;
> +}
> +
> +static jobject convert_to_swigtype(void *value, void *ctx)
> +{
> + /* ctx is a 'swig_type_info *' */
> + return SWIG_NewPointerObj(value, ctx, 0);
> +}
> +
> +static jobject convert_svn_string_t(void *value, void *ctx)
> +{
> + JNIEnv *jenv = (JNIEnv *) ctx;
> + const svn_string_t *s = value;
> +
> + /* ### borrowing from value in the pool. or should we copy? note
> + ### that copying is "safest" */
> +
> + return JCALL2(NewString, jenv, s->data, s->len);
> +}
> +
> +
> +jobject svn_swig_java_prophash_to_dict(JNIEnv *jenv, apr_hash_t *hash)
> +{
> + return convert_hash(hash, convert_svn_string_t, jenv);
> +}
> +
> +jobject svn_swig_java_convert_hash(JNIEnv *jenv, apr_hash_t
> *hash, swig_type_info *type)
> +{
> + return convert_hash(hash, convert_to_swigtype, type);
> +}
> +
> +jobject svn_swig_java_c_strings_to_list(JNIEnv *jenv, char **strings)
> +{
> + jclass cls = JCALL1(FindClass, jenv, "java/util/ArrayList");
> + jobject list = JCALL2(NewObject, jenv, cls,
> + JCALL3(GetMethodID, jenv, cls, "<init>", "()V"));
> + jmethodID add = JCALL3(GetMethodID, jenv, cls, "add",
> "(Ljava/lang/Object;)Z");
> + char *s;
> + jobject obj;
> + while ((s = *strings++) != NULL)
> + {
> + obj = JCALL2(NewString, jenv, s, strlen(s));
> +
> + if (obj == NULL)
> + goto error;
> +
> + JCALL3(CallBooleanMethod, jenv, list, add, obj);
> +
> + JCALL1(DeleteLocalRef, jenv, obj);
> + }
> +
> + return list;
> +
> + error:
> + JCALL1(DeleteLocalRef, jenv, list);
> + return NULL;
> +}
> +
> +jobject svn_swig_java_array_to_list(JNIEnv *jenv, const
> apr_array_header_t *strings)
> +{
> + jclass cls = JCALL1(FindClass, jenv, "java/util/ArrayList");
> + jobject list = JCALL3(NewObject, jenv, cls,
> + JCALL3(GetMethodID, jenv, cls, "<init>", "(I)V"),
> + strings->nelts);
> + int i;
> + jobject obj;
> +
> + for (i = 0; i < strings->nelts; ++i)
> + {
> + const char *s;
> +
> + s = APR_ARRAY_IDX(strings, i, const char *);
> + obj = JCALL2(NewString, jenv, s, strlen(s));
> + if (obj == NULL)
> + goto error;
> + PyList_SET_ITEM(list, i, obj);
> + JCALL1(DeleteLocaleRef, jenv, obj);
> + }
> +
> + return list;
> +
> + error:
> + JCALL1(DeleteLocaleRef, jenv, list);
> + return NULL;
> +}
> +
> +const apr_array_header_t *svn_swig_java_strings_to_array(JNIEnv *jenv,
> + jobject source,
> +
> apr_pool_t *pool)
> +{
> + int targlen;
> + apr_array_header_t *temp;
> +
> + jclass cls = JCALL1(FindClass, jenv, "lang/util/List");
> + jmethodID size = JCALL3(GetMethodID, jenv, cls, "size", "()I");
> + jmethodID get = JCALL3(GetMethodID, jenv, cls, "get",
> + "(I)Ljava/lang/Object;");
> + if (!JCALL2(IsInstanceOf, jenv, source, cls))
> + {
> + /* FIXME: Resport by error (perhaps by throw an Exception)
> + PyErr_SetString(PyExc_TypeError, "not a sequence"); */
> + return NULL;
> + }
> + targlen = JCALL2(CallIntegerMethod, jenv, source, size);
> + temp = apr_array_make(pool, targlen, sizeof(const char *));
> + while (targlen--)
> + {
> + jobject o = JCALL3(CallObjectMethod, jenv, source, get, targlen);
> + if (o == NULL)
> + return NULL;
> + if (!PyString_Check(o))
> + {
> + JCALL1(DeleteLocalRef, jenv, o);
> + /* FIXME: Resport by error (perhaps by throw an Exception)
> + PyErr_SetString(PyExc_TypeError, "not a sequence"); */
> + return NULL;
> + }
> + APR_ARRAY_IDX(temp, targlen, const char *) = PyString_AS_STRING(o);
> + JCALL1(DeleteLocalRef, jenv, o);
> + }
> + return temp;
> +}
> +
> +
> +static svn_error_t * convert_java_error(JNIEnv *jenv, apr_pool_t *pool)
> +{
> + /* ### need to fetch the Python error and map it to an svn_error_t */
> +
> + return svn_error_create(APR_EGENERAL, 0, NULL, pool,
> + "the Python callback raised an exception");
> +}
> +
> +static item_baton * make_baton(JNIEnv *jenv, apr_pool_t *pool,
> + jobject editor, jobject baton)
> +{
> + item_baton *newb = apr_palloc(pool, sizeof(*newb));
> +
> + /* one more reference to the editor. */
> + Py_INCREF(editor);
> +
> + /* note: we take the caller's reference to 'baton' */
> +
> + newb->editor = editor;
> + newb->baton = baton;
> + newb->pool = pool;
> +
> + return newb;
> +}
> +
> +static svn_error_t * close_baton(JNIEnv *jenv, void *baton,
> const char *method)
> +{
> + item_baton *ib = baton;
> + jobject result;
> +
> + /* If there is no baton object, then it is an edit_baton, and we should
> + not bother to pass an object. Note that we still shove a NULL onto
> + the stack, but the format specified just won't reference it. */
> + /* ### python doesn't have 'const' on the method name and format */
> + if ((result = PyObject_CallMethod(ib->editor, (char *)method,
> + ib->baton ? (char *)"O" : NULL,
> + ib->baton)) == NULL)
> + {
> + return convert_python_error(ib->pool);
> + }
> +
> + /* there is no return value, so just toss this object
> (probably Py_None) */
> + Py_DECREF(result);
> +
> + /* We're now done with the baton. Since there isn't really a free, all
> + we need to do is note that its objects are no longer referenced by
> + the baton. */
> + Py_DECREF(ib->editor);
> + Py_XDECREF(ib->baton);
> +
> +#ifdef SVN_DEBUG
> + ib->editor = ib->baton = NULL;
> +#endif
> +
> + return SVN_NO_ERROR;
> +}
> +
> +static svn_error_t * thunk_set_target_revision(void *edit_baton,
> + svn_revnum_t
> target_revision)
> +{
> + item_baton *ib = edit_baton;
> + jobject result;
> +
> + /* ### python doesn't have 'const' on the method name and format */
> + if ((result = PyObject_CallMethod(ib->editor, (char
> *)"set_target_revision",
> + (char *)"l",
> target_revision)) == NULL)
> + {
> + return convert_python_error(ib->pool);
> + }
> +
> + /* there is no return value, so just toss this object
> (probably Py_None) */
> + Py_DECREF(result);
> +
> + return SVN_NO_ERROR;
> +}
> +
> +static svn_error_t * thunk_open_root(void *edit_baton,
> + svn_revnum_t base_revision,
> + apr_pool_t *dir_pool,
> + void **root_baton)
> +{
> + item_baton *ib = edit_baton;
> + jobject result;
> +
> + /* ### python doesn't have 'const' on the method name and format */
> + if ((result = PyObject_CallMethod(ib->editor, (char *)"open_root",
> + (char *)"lO&", base_revision,
> + make_ob_pool, dir_pool)) == NULL)
> + {
> + return convert_python_error(dir_pool);
> + }
> +
> + /* make_baton takes our 'result' reference */
> + *root_baton = make_baton(dir_pool, ib->editor, result);
> +
> + return SVN_NO_ERROR;
> +}
> +
> +static svn_error_t * thunk_delete_entry(const char *path,
> + svn_revnum_t revision,
> + void *parent_baton,
> + apr_pool_t *pool)
> +{
> + item_baton *ib = parent_baton;
> + jobject result;
> +
> + /* ### python doesn't have 'const' on the method name and format */
> + if ((result = PyObject_CallMethod(ib->editor, (char *)"delete_entry",
> + (char *)"slOO&", path,
> revision, ib->baton,
> + make_ob_pool, pool)) == NULL)
> + {
> + return convert_python_error(pool);
> + }
> +
> + /* there is no return value, so just toss this object
> (probably Py_None) */
> + Py_DECREF(result);
> +
> + return SVN_NO_ERROR;
> +}
> +
> +static svn_error_t * thunk_add_directory(const char *path,
> + void *parent_baton,
> + const char *copyfrom_path,
> + svn_revnum_t copyfrom_revision,
> + apr_pool_t *dir_pool,
> + void **child_baton)
> +{
> + item_baton *ib = parent_baton;
> + jobject result;
> +
> + /* ### python doesn't have 'const' on the method name and format */
> + if ((result = PyObject_CallMethod(ib->editor, (char *)"add_directory",
> + (char *)"sOslO&", path, ib->baton,
> + copyfrom_path, copyfrom_revision,
> + make_ob_pool, dir_pool)) == NULL)
> + {
> + return convert_python_error(dir_pool);
> + }
> +
> + /* make_baton takes our 'result' reference */
> + *child_baton = make_baton(dir_pool, ib->editor, result);
> +
> + return SVN_NO_ERROR;
> +}
> +
> +static svn_error_t * thunk_open_directory(const char *path,
> + void *parent_baton,
> + svn_revnum_t base_revision,
> + apr_pool_t *dir_pool,
> + void **child_baton)
> +{
> + item_baton *ib = parent_baton;
> + jobject result;
> +
> + /* ### python doesn't have 'const' on the method name and format */
> + if ((result = PyObject_CallMethod(ib->editor, (char *)"open_directory",
> + (char *)"sOlO&", path, ib->baton,
> + base_revision,
> + make_ob_pool, dir_pool)) == NULL)
> + {
> + return convert_python_error(dir_pool);
> + }
> +
> + /* make_baton takes our 'result' reference */
> + *child_baton = make_baton(dir_pool, ib->editor, result);
> +
> + return SVN_NO_ERROR;
> +}
> +
> +static svn_error_t * thunk_change_dir_prop(void *dir_baton,
> + const char *name,
> + const svn_string_t *value,
> + apr_pool_t *pool)
> +{
> + item_baton *ib = dir_baton;
> + jobject result;
> +
> + /* ### python doesn't have 'const' on the method name and format */
> + if ((result = PyObject_CallMethod(ib->editor, (char
> *)"change_dir_prop",
> + (char *)"Oss#O&", ib->baton, name,
> + value->data, value->len,
> + make_ob_pool, pool)) == NULL)
> + {
> + return convert_python_error(pool);
> + }
> +
> + /* there is no return value, so just toss this object
> (probably Py_None) */
> + Py_DECREF(result);
> +
> + return SVN_NO_ERROR;
> +}
> +
> +static svn_error_t * thunk_close_directory(void *dir_baton)
> +{
> + return close_baton(dir_baton, "close_directory");
> +}
> +
> +static svn_error_t * thunk_add_file(const char *path,
> + void *parent_baton,
> + const char *copyfrom_path,
> + svn_revnum_t copyfrom_revision,
> + apr_pool_t *file_pool,
> + void **file_baton)
> +{
> + item_baton *ib = parent_baton;
> + jobject result;
> +
> + /* ### python doesn't have 'const' on the method name and format */
> + if ((result = PyObject_CallMethod(ib->editor, (char *)"add_file",
> + (char *)"sOslO&", path, ib->baton,
> + copyfrom_path, copyfrom_revision,
> + make_ob_pool, file_pool)) == NULL)
> + {
> + return convert_python_error(file_pool);
> + }
> +
> + /* make_baton takes our 'result' reference */
> + *file_baton = make_baton(file_pool, ib->editor, result);
> +
> + return SVN_NO_ERROR;
> +}
> +
> +static svn_error_t * thunk_open_file(const char *path,
> + void *parent_baton,
> + svn_revnum_t base_revision,
> + apr_pool_t *file_pool,
> + void **file_baton)
> +{
> + item_baton *ib = parent_baton;
> + jobject result;
> +
> + /* ### python doesn't have 'const' on the method name and format */
> + if ((result = PyObject_CallMethod(ib->editor, (char *)"open_file",
> + (char *)"sOlO&", path, ib->baton,
> + base_revision,
> + make_ob_pool, file_pool)) == NULL)
> + {
> + return convert_python_error(file_pool);
> + }
> +
> + /* make_baton takes our 'result' reference */
> + *file_baton = make_baton(file_pool, ib->editor, result);
> +
> + return SVN_NO_ERROR;
> +}
> +
> +static svn_error_t * thunk_window_handler(svn_txdelta_window_t *window,
> + void *baton)
> +{
> + handler_baton *hb = baton;
> + jobject result;
> +
> + if (window == NULL)
> + {
> + /* the last call; it closes the handler */
> +
> + /* invoke the handler with None for the window */
> + /* ### python doesn't have 'const' on the format */
> + result = PyObject_CallFunction(hb->handler, (char *)"O", Py_None);
> +
> + /* we no longer need to refer to the handler object */
> + Py_DECREF(hb->handler);
> + }
> + else
> + {
> + /* invoke the handler with the window */
> + /* ### python doesn't have 'const' on the format */
> + result = PyObject_CallFunction(hb->handler,
> + (char *)"O&",
> make_ob_window, window);
> + }
> +
> + if (result == NULL)
> + return convert_python_error(hb->pool);
> +
> + /* there is no return value, so just toss this object
> (probably Py_None) */
> + Py_DECREF(result);
> +
> + return SVN_NO_ERROR;
> +}
> +
> +static svn_error_t * thunk_apply_textdelta(
> + void *file_baton,
> + svn_txdelta_window_handler_t *handler,
> + void **h_baton)
> +{
> + item_baton *ib = file_baton;
> + jobject result;
> +
> + /* ### python doesn't have 'const' on the method name and format */
> + if ((result = PyObject_CallMethod(ib->editor, (char
> *)"apply_textdelta",
> + (char *)"O", ib->baton)) == NULL)
> + {
> + return convert_python_error(ib->pool);
> + }
> +
> + if (result == Py_None)
> + {
> + Py_DECREF(result);
> + *handler = NULL;
> + *h_baton = NULL;
> + }
> + else
> + {
> + handler_baton *hb = apr_palloc(ib->pool, sizeof(*hb));
> +
> + /* return the thunk for invoking the handler. the baton takes our
> + 'result' reference. */
> + hb->handler = result;
> + hb->pool = ib->pool;
> +
> + *handler = thunk_window_handler;
> + *h_baton = hb;
> + }
> +
> + return SVN_NO_ERROR;
> +}
> +
> +static svn_error_t * thunk_change_file_prop(void *file_baton,
> + const char *name,
> + const svn_string_t *value,
> + apr_pool_t *pool)
> +{
> + item_baton *ib = file_baton;
> + jobject result;
> +
> + /* ### python doesn't have 'const' on the method name and format */
> + if ((result = PyObject_CallMethod(ib->editor, (char
> *)"change_file_prop",
> + (char *)"Oss#O&", ib->baton, name,
> + value->data, value->len,
> + make_ob_pool, pool)) == NULL)
> + {
> + return convert_python_error(pool);
> + }
> +
> + /* there is no return value, so just toss this object
> (probably Py_None) */
> + Py_DECREF(result);
> +
> + return SVN_NO_ERROR;
> +}
> +
> +static svn_error_t * thunk_close_file(void *file_baton)
> +{
> + return close_baton(file_baton, "close_file");
> +}
> +
> +static svn_error_t * thunk_close_edit(void *edit_baton)
> +{
> + return close_baton(edit_baton, "close_edit");
> +}
> +
> +static svn_error_t * thunk_abort_edit(void *edit_baton)
> +{
> + return close_baton(edit_baton, "abort_edit");
> +}
> +
> +static const svn_delta_editor_t thunk_editor = {
> + thunk_set_target_revision,
> + thunk_open_root,
> + thunk_delete_entry,
> + thunk_add_directory,
> + thunk_open_directory,
> + thunk_change_dir_prop,
> + thunk_close_directory,
> + thunk_add_file,
> + thunk_open_file,
> + thunk_apply_textdelta,
> + thunk_change_file_prop,
> + thunk_close_file,
> + thunk_close_edit,
> + thunk_abort_edit
> +};
> +
> +void svn_swig_java_make_editor(JNIEnv *jenv,
> + const svn_delta_editor_t **editor,
> + void **edit_baton,
> + jobject java_editor,
> + apr_pool_t *pool)
> +{
> + *editor = &thunk_editor;
> + *edit_baton = make_baton(pool, java_editor, NULL);
> +}
> +
> +/* ----------------------------------------------------------------
> + * local variables:
> + * eval: (load-file "../../../tools/dev/svn-dev.el")
> + * end:
> + */
> Index: ./svn_client.i
> ===================================================================
> --- ./svn_client.i
> +++ ./svn_client.i Wed Oct 16 09:15:22 2002
> @@ -98,6 +98,12 @@
> }
> $result = t_output_helper($result, list);
> }
> +%typemap(java,argout) apr_hash_t **statushash {
> + /* FIXME: Use JNI equiv of Java type SWIGTYPE_p_svn_wc_status_t */
> + $result = t_output_helper(
> + $result,
> + svn_swig_java_convert_hash(*$1, SWIGTYPE_p_svn_wc_status_t));
> +}
>
> /*
> -----------------------------------------------------------------------
> handle the "statushash" OUTPUT param for svn_client_status()
> @@ -128,6 +134,10 @@
> #ifdef SWIGPYTHON
> #include "swigutil_py.h"
> #endif
> +
> +#ifdef SWIGJAVA
> +#include "swigutil_java.h"
> +#endif
> %}
>
> %include svn_client.h
> Index: ./swigutil_java.h
> ===================================================================
> --- ./swigutil_java.h
> +++ ./swigutil_java.h Fri Oct 11 19:24:04 2002
> @@ -0,0 +1,103 @@
> +/*
> + * swigutil_java.h : utility functions and stuff for the SWIG
> Java bindings
> + *
> + * ====================================================================
> + * Copyright (c) 2000-2002 CollabNet. All rights reserved.
> + *
> + * This software is licensed as described in the file COPYING, which
> + * you should have received as part of this distribution. The terms
> + * are also available at http://subversion.tigris.org/license-1.html.
> + * If newer versions of this license are posted there, you may use a
> + * newer version instead, at your option.
> + *
> + * This software consists of voluntary contributions made by many
> + * individuals. For exact contribution history, see the revision
> + * history and logs, available at http://subversion.tigris.org/.
> + * ====================================================================
> + */
> +
> +
> +#ifndef SVN_SWIG_SWIGUTIL_JAVA_H
> +#define SVN_SWIG_SWIGUTIL_JAVA_H
> +
> +#include <jni.h>
> +
> +#include <apr.h>
> +#include <apr_pools.h>
> +#include <apr_strings.h>
> +#include <apr_hash.h>
> +#include <apr_tables.h>
> +
> +#include "svn_types.h"
> +#include "svn_string.h"
> +#include "svn_delta.h"
> +
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif /* __cplusplus */
> +
> +>
> +/* If this file is being included outside of a wrapper file, then need to
> + create stubs for some of the SWIG types. */
> +
> +/* if SWIGEXPORT is defined, then we're in a wrapper. otherwise, we need
> + the prototypes and type definitions. */
> +#ifndef SWIGEXPORT
> +#define SVN_NEED_SWIG_TYPES
> +#endif
> +
> +#ifdef SVN_NEED_SWIG_TYPES
> +
> +typedef struct _unnamed swig_type_info;
> +jobject *SWIG_NewPointerObj(JNIEnv *jenv, void *, swig_type_info
> *, int own);
> +swig_type_info *SWIG_TypeQuery(JNIEnv *jenv, const char *name);
> +
> +#endif /* SVN_NEED_SWIG_TYPES */
> +
> +>
> +/* helper function to convert an apr_hash_t* (char* -> svnstring_t*) to
> + a Java Map */
> +jobject svn_swig_java_prophash_to_dict(JNIEnv *jenv, apr_hash_t *hash);
> +
> +/* convert a hash of 'const char *' -> TYPE into a Java Map */
> +jobject svn_swig_java_convert_hash(JNIEnv *jenv, apr_hash_t *hash,
> + swig_type_info *type);
> +
> +/* helper function to convert a 'char **' into a Java List of String
> + objects */
> +jobject svn_swig_java_c_strings_to_list(JNIEnv *jenv, char **strings);
> +
> +/* helper function to convert an array of 'const char *' to a
> Java List of
> + String objects */
> +jobject svn_swig_java_array_to_list(JNIEnv *jenv,
> + const apr_array_header_t *strings);
> +
> +/* helper function to convert a Java List of String objects into an
> + 'apr_array_header_t *' of 'const char *' objects. Note that the
> + objects must remain alive -- the values are not copied. This is
> + appropriate for incoming arguments which are defined to last the
> + duration of the function's execution. */
> +const apr_array_header_t *svn_swig_java_strings_to_array(JNIEnv *jenv,
> + jobject source,
> +
> apr_pool_t *pool);
> +
> +/* make a editor that "thunks" from C callbacks up to Java */
> +void svn_swig_java_make_editor(JNIEnv *jenv,
> + const svn_delta_editor_t **editor,
> + void **edit_baton,
> + jobject java_editor,
> + apr_pool_t *pool);
> +
> +#ifdef __cplusplus
> +}
> +#endif /* __cplusplus */
> +
> +#endif /* SVN_SWIG_SWIGUTIL_JAVA_H */
> +
> +>
> +/* ----------------------------------------------------------------
> + * local variables:
> + * eval: (load-file "../../../tools/dev/svn-dev.el")
> + * end:
> + */
> Index: ./util.i
> ===================================================================
> --- ./util.i
> +++ ./util.i Fri Oct 11 19:46:41 2002
> @@ -189,4 +189,8 @@
> #ifdef SWIGPYTHON
> #include "swigutil_py.h"
> #endif
> +
> +#ifdef SWIGJAVA
> +#include "swigutil_java.h"
> +#endif
> %}
> Index: ./svn_repos.i
> ===================================================================
> --- ./svn_repos.i
> +++ ./svn_repos.i Fri Oct 11 19:46:41 2002
> @@ -62,4 +62,8 @@
> #ifdef SWIGPYTHON
> #include "swigutil_py.h"
> #endif
> +
> +#ifdef SWIGJAVA
> +#include "swigutil_java.h"
> +#endif
> %}
> Index: ./svn_delta.i
> ===================================================================
> --- ./svn_delta.i
> +++ ./svn_delta.i Fri Oct 11 19:46:41 2002
> @@ -82,4 +82,8 @@
> #ifdef SWIGPYTHON
> #include "swigutil_py.h"
> #endif
> +
> +#ifdef SWIGJAVA
> +#include "swigutil_java.h"
> +#endif
> %}
> Index: ./apr.i
> ===================================================================
> --- ./apr.i
> +++ ./apr.i Wed Oct 16 08:15:40 2002
> @@ -62,6 +62,12 @@
> %typemap(python,argout,fragment="t_output_helper") apr_time_t * {
> $result = t_output_helper($result, PyLong_FromLongLong(*$1));
> }
> +%typemap(java,argout) apr_time_t * {
> + jclass cls = JCALL1(FindClass, jenv, "java/lang/Long");
> + jmethodID ctor = JCALL3(GetMethodID, jenv, cls, "<init>", "(J)V");
> + jobject l = JCALL3(NewObject, jenv, cls, ctor, (jlong) *$1);
> + $result = t_output_helper($result, JCALL1(NewGlobalRef, jenv, l));
> +}
>
> /*
> -----------------------------------------------------------------------
> create some INOUT typemaps for apr_size_t
> @@ -73,6 +79,12 @@
> temp = (apr_size_t) PyInt_AsLong($input);
> $1 = &temp;
> }
> +%typemap(java,in) apr_size_t *INOUT (apr_size_t temp) {
> + jclass cls = JCALL1(FindClass, jenv, "java/lang/Long");
> + jmethodID mid = JCALL3(GetStaticMethodID, jenv, cls,
> "longValue", "()J");
> + temp = (apr_size_t) JCALL2(CallStaticLongMethod, jenv, mid, $input);
> + $1 = &temp;
> +}
>
> /*
> -----------------------------------------------------------------------
> create an OUTPUT argument typemap for an apr_hash_t **
> @@ -93,6 +105,12 @@
> Py_DECREF($result);
> $result = svn_swig_py_prophash_to_dict(*$1);
> }
> +%typemap(java,argout) apr_hash_t **PROPHASH {
> + /* toss prior result, get new result from the hash */
> + JCALL1(DeleteGlobalRef, jenv, $result);
> + $result = JCALL1(NewGlobalRef, jenv,
> + svn_swig_java_prophash_to_dict(jenv, *$1));
> +}
>
> /*
> -----------------------------------------------------------------------
> apr_file_t ** is always an OUT param
> @@ -105,6 +123,13 @@
> $result = t_output_helper(
> $result,
> SWIG_NewPointerObj(*$1, $*1_descriptor, 0));
> +}
> +%typemap(java,argout) apr_file_t ** {
> + /* HELP: Is there a JNI equivalent of SWIG_NewPointerObj, or is
> + this actually a cross-language typemap? */
> + $result = t_output_helper(
> + $result,
> + SWIG_NewPointerObj(*$1, $*1_descriptor, 0));
> }
>
> /*
> ----------------------------------------------------------------------- */
> Index: ./Makefile
> ===================================================================
> --- ./Makefile
> +++ ./Makefile Wed Oct 16 09:14:06 2002
> @@ -0,0 +1,15 @@
> +# TODO: Use -swiglig argument to avoid the need for SWIG-internal paths.
> +SWIG_CMD=/usr/local/swig/bin/swig -c -java -noproxy -module
> 'svn_jni' -I'.' -I'../../include'
> -I'/home/dlr/src/apache.org/apr/include'
> -I'/usr/local/swig/lib/swig1.3' -I'/usr/local/swig/lib/swig1.3/java'
> +
> +build-java: swig-java
> +
> +swig-java:
> + for source in *.i; do \
> + target="`echo -n $$source | perl -pe 's/..$$/.jni.c/'`"; \
> + $(SWIG_CMD) -o $$target $$source; \
> + done; unset target source
> +
> +clean: swig-java-clean
> +
> +swig-java-clean:
> + rm -f *.jni.c *.java
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
> For additional commands, e-mail: dev-help@subversion.tigris.org
>
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: SWIG Java bindings
Posted by Daniel Rall <dl...@finemaltcoding.com>.
Morten Ludvigsen <mo...@yahoo.co.uk> writes:
> Is anyone actively working on SWIG-Java bindings?
>
> If not I think I will take a crack at it :-)
Hi Morten. I've done a small amount of work on them. What I have is
swigging successfully, but may not compile (haven't tried yet) and
surely won't run (a lot of it is still incomplete/stubbed/broken). I
hope it's a useful starting place for you, and am very interested in
seeing some diffs with what ever progress you find time to make.
Hopefully I'll have time to help out a little more as well.
--
Daniel Rall <dl...@finemaltcoding.com>
Index: ./svn_types.i
===================================================================
--- ./svn_types.i
+++ ./svn_types.i Wed Oct 16 09:01:38 2002
@@ -83,6 +83,9 @@
$1 = PyString_AS_STRING($input);
$2 = PyString_GET_SIZE($input);
}
+%typemap(java, in) (const char *PTR, apr_size_t LEN) {
+ /* FIXME: This is just a stub -- implement JNI code! */
+}
/* -----------------------------------------------------------------------
Define a generic arginit mapping for pools.
Index: ./svn_string.i
===================================================================
--- ./svn_string.i
+++ ./svn_string.i Wed Oct 16 09:01:03 2002
@@ -42,6 +42,10 @@
}
$result = t_output_helper($result, s);
}
+%typemap(java,argout,fragment="t_output_helper") RET_STRING {
+ /* FIXME: This is just a stub -- implement JNI code! */
+ return NULL;
+}
/* -----------------------------------------------------------------------
TYPE: svn_stringbuf_t
@@ -137,5 +141,8 @@
if ($1 == NULL)
return NULL;
}
+%typemap(java,in) const apr_array_header_t *STRINGLIST {
+ /* FIXME: This is just a stub -- implement JNI code! */
+}
/* ----------------------------------------------------------------------- */
Index: ./svn_fs.i
===================================================================
--- ./svn_fs.i
+++ ./svn_fs.i Fri Oct 11 19:46:41 2002
@@ -113,4 +113,8 @@
#ifdef SWIGPYTHON
#include "swigutil_py.h"
#endif
+
+#ifdef SWIGJAVA
+#include "swigutil_java.h"
+#endif
%}
Index: ./swigutil_java.c
===================================================================
--- ./swigutil_java.c
+++ ./swigutil_java.c Fri Oct 11 19:24:04 2002
@@ -0,0 +1,602 @@
+/*
+ * swigutil_java.c: utility functions for the SWIG Java bindings
+ *
+ * ====================================================================
+ * Copyright (c) 2000-2002 CollabNet. All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals. For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ */
+
+
+#include <jni.h>
+
+#include <apr_pools.h>
+#include <apr_hash.h>
+
+#include "svn_string.h"
+#include "svn_delta.h"
+
+#include "swigutil_java.h"
+
+
+/* this baton is used for the editor, directory, and file batons. */
+typedef struct {
+ jobject editor; /* the editor handling the callbacks */
+ jobject baton; /* the dir/file baton (or NULL for edit baton) */
+ apr_pool_t *pool; /* pool to use for errors */
+} item_baton;
+
+typedef struct {
+ jobject handler; /* the window handler (a callable) */
+ apr_pool_t *pool; /* a pool for constructing errors */
+} handler_baton;
+
+
+static jobject make_pointer(const char *typename, void *ptr)
+{
+ /* ### cache the swig_type_info at some point? */
+ return SWIG_NewPointerObj(ptr, SWIG_TypeQuery(typename), 0);
+}
+
+/* for use by the "O&" format specifier */
+static jobject make_ob_pool(void *ptr)
+{
+ return make_pointer("apr_pool_t *", ptr);
+}
+
+/* for use by the "O&" format specifier */
+static jobject make_ob_window(void *ptr)
+{
+ return make_pointer("svn_txdelta_window_t *", ptr);
+}
+
+static jobject convert_hash(apr_hash_t *hash,
+ jobject (*converter_func)(void *value,
+ void *ctx),
+ void *ctx)
+{
+ apr_hash_index_t *hi;
+ jclass cls = JCALL1(FindClass, jenv, "java/util/HashMap");
+ jobject dict = JCALL3(NewObject, jenv, cls,
+ JCALL3(GetMethodID, jenv, cls, "<init>", "(I)V"),
+ (jint) apr_hash_count(hash));
+ jmethoID put = JCALL3(GetMethodID, jenv, cls, "put",
+ "(Ljava/lang/Object;Ljava/lang/Object;)"
+ "Ljava/lang/Object;"),
+
+ if (dict == NULL)
+ return NULL;
+
+ for (hi = apr_hash_first(NULL, hash); hi; hi = apr_hash_next(hi))
+ {
+ const void *key;
+ void *val;
+ jobject value;
+
+ apr_hash_this(hi, &key, NULL, &val);
+ value = (*converter_func)(val, ctx);
+ JCALL3(CallObjectMethod, jenv, put,
+ JCALL2(NewString, jenv, key, strlen(key)), value);
+ JCALL1(DeleteLocalRef, jenv, value);
+ }
+
+ return dict;
+}
+
+static jobject convert_to_swigtype(void *value, void *ctx)
+{
+ /* ctx is a 'swig_type_info *' */
+ return SWIG_NewPointerObj(value, ctx, 0);
+}
+
+static jobject convert_svn_string_t(void *value, void *ctx)
+{
+ JNIEnv *jenv = (JNIEnv *) ctx;
+ const svn_string_t *s = value;
+
+ /* ### borrowing from value in the pool. or should we copy? note
+ ### that copying is "safest" */
+
+ return JCALL2(NewString, jenv, s->data, s->len);
+}
+
+
+jobject svn_swig_java_prophash_to_dict(JNIEnv *jenv, apr_hash_t *hash)
+{
+ return convert_hash(hash, convert_svn_string_t, jenv);
+}
+
+jobject svn_swig_java_convert_hash(JNIEnv *jenv, apr_hash_t *hash, swig_type_info *type)
+{
+ return convert_hash(hash, convert_to_swigtype, type);
+}
+
+jobject svn_swig_java_c_strings_to_list(JNIEnv *jenv, char **strings)
+{
+ jclass cls = JCALL1(FindClass, jenv, "java/util/ArrayList");
+ jobject list = JCALL2(NewObject, jenv, cls,
+ JCALL3(GetMethodID, jenv, cls, "<init>", "()V"));
+ jmethodID add = JCALL3(GetMethodID, jenv, cls, "add", "(Ljava/lang/Object;)Z");
+ char *s;
+ jobject obj;
+ while ((s = *strings++) != NULL)
+ {
+ obj = JCALL2(NewString, jenv, s, strlen(s));
+
+ if (obj == NULL)
+ goto error;
+
+ JCALL3(CallBooleanMethod, jenv, list, add, obj);
+
+ JCALL1(DeleteLocalRef, jenv, obj);
+ }
+
+ return list;
+
+ error:
+ JCALL1(DeleteLocalRef, jenv, list);
+ return NULL;
+}
+
+jobject svn_swig_java_array_to_list(JNIEnv *jenv, const apr_array_header_t *strings)
+{
+ jclass cls = JCALL1(FindClass, jenv, "java/util/ArrayList");
+ jobject list = JCALL3(NewObject, jenv, cls,
+ JCALL3(GetMethodID, jenv, cls, "<init>", "(I)V"),
+ strings->nelts);
+ int i;
+ jobject obj;
+
+ for (i = 0; i < strings->nelts; ++i)
+ {
+ const char *s;
+
+ s = APR_ARRAY_IDX(strings, i, const char *);
+ obj = JCALL2(NewString, jenv, s, strlen(s));
+ if (obj == NULL)
+ goto error;
+ PyList_SET_ITEM(list, i, obj);
+ JCALL1(DeleteLocaleRef, jenv, obj);
+ }
+
+ return list;
+
+ error:
+ JCALL1(DeleteLocaleRef, jenv, list);
+ return NULL;
+}
+
+const apr_array_header_t *svn_swig_java_strings_to_array(JNIEnv *jenv,
+ jobject source,
+ apr_pool_t *pool)
+{
+ int targlen;
+ apr_array_header_t *temp;
+
+ jclass cls = JCALL1(FindClass, jenv, "lang/util/List");
+ jmethodID size = JCALL3(GetMethodID, jenv, cls, "size", "()I");
+ jmethodID get = JCALL3(GetMethodID, jenv, cls, "get",
+ "(I)Ljava/lang/Object;");
+ if (!JCALL2(IsInstanceOf, jenv, source, cls))
+ {
+ /* FIXME: Resport by error (perhaps by throw an Exception)
+ PyErr_SetString(PyExc_TypeError, "not a sequence"); */
+ return NULL;
+ }
+ targlen = JCALL2(CallIntegerMethod, jenv, source, size);
+ temp = apr_array_make(pool, targlen, sizeof(const char *));
+ while (targlen--)
+ {
+ jobject o = JCALL3(CallObjectMethod, jenv, source, get, targlen);
+ if (o == NULL)
+ return NULL;
+ if (!PyString_Check(o))
+ {
+ JCALL1(DeleteLocalRef, jenv, o);
+ /* FIXME: Resport by error (perhaps by throw an Exception)
+ PyErr_SetString(PyExc_TypeError, "not a sequence"); */
+ return NULL;
+ }
+ APR_ARRAY_IDX(temp, targlen, const char *) = PyString_AS_STRING(o);
+ JCALL1(DeleteLocalRef, jenv, o);
+ }
+ return temp;
+}
+
+
+static svn_error_t * convert_java_error(JNIEnv *jenv, apr_pool_t *pool)
+{
+ /* ### need to fetch the Python error and map it to an svn_error_t */
+
+ return svn_error_create(APR_EGENERAL, 0, NULL, pool,
+ "the Python callback raised an exception");
+}
+
+static item_baton * make_baton(JNIEnv *jenv, apr_pool_t *pool,
+ jobject editor, jobject baton)
+{
+ item_baton *newb = apr_palloc(pool, sizeof(*newb));
+
+ /* one more reference to the editor. */
+ Py_INCREF(editor);
+
+ /* note: we take the caller's reference to 'baton' */
+
+ newb->editor = editor;
+ newb->baton = baton;
+ newb->pool = pool;
+
+ return newb;
+}
+
+static svn_error_t * close_baton(JNIEnv *jenv, void *baton, const char *method)
+{
+ item_baton *ib = baton;
+ jobject result;
+
+ /* If there is no baton object, then it is an edit_baton, and we should
+ not bother to pass an object. Note that we still shove a NULL onto
+ the stack, but the format specified just won't reference it. */
+ /* ### python doesn't have 'const' on the method name and format */
+ if ((result = PyObject_CallMethod(ib->editor, (char *)method,
+ ib->baton ? (char *)"O" : NULL,
+ ib->baton)) == NULL)
+ {
+ return convert_python_error(ib->pool);
+ }
+
+ /* there is no return value, so just toss this object (probably Py_None) */
+ Py_DECREF(result);
+
+ /* We're now done with the baton. Since there isn't really a free, all
+ we need to do is note that its objects are no longer referenced by
+ the baton. */
+ Py_DECREF(ib->editor);
+ Py_XDECREF(ib->baton);
+
+#ifdef SVN_DEBUG
+ ib->editor = ib->baton = NULL;
+#endif
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_set_target_revision(void *edit_baton,
+ svn_revnum_t target_revision)
+{
+ item_baton *ib = edit_baton;
+ jobject result;
+
+ /* ### python doesn't have 'const' on the method name and format */
+ if ((result = PyObject_CallMethod(ib->editor, (char *)"set_target_revision",
+ (char *)"l", target_revision)) == NULL)
+ {
+ return convert_python_error(ib->pool);
+ }
+
+ /* there is no return value, so just toss this object (probably Py_None) */
+ Py_DECREF(result);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_open_root(void *edit_baton,
+ svn_revnum_t base_revision,
+ apr_pool_t *dir_pool,
+ void **root_baton)
+{
+ item_baton *ib = edit_baton;
+ jobject result;
+
+ /* ### python doesn't have 'const' on the method name and format */
+ if ((result = PyObject_CallMethod(ib->editor, (char *)"open_root",
+ (char *)"lO&", base_revision,
+ make_ob_pool, dir_pool)) == NULL)
+ {
+ return convert_python_error(dir_pool);
+ }
+
+ /* make_baton takes our 'result' reference */
+ *root_baton = make_baton(dir_pool, ib->editor, result);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_delete_entry(const char *path,
+ svn_revnum_t revision,
+ void *parent_baton,
+ apr_pool_t *pool)
+{
+ item_baton *ib = parent_baton;
+ jobject result;
+
+ /* ### python doesn't have 'const' on the method name and format */
+ if ((result = PyObject_CallMethod(ib->editor, (char *)"delete_entry",
+ (char *)"slOO&", path, revision, ib->baton,
+ make_ob_pool, pool)) == NULL)
+ {
+ return convert_python_error(pool);
+ }
+
+ /* there is no return value, so just toss this object (probably Py_None) */
+ Py_DECREF(result);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_add_directory(const char *path,
+ void *parent_baton,
+ const char *copyfrom_path,
+ svn_revnum_t copyfrom_revision,
+ apr_pool_t *dir_pool,
+ void **child_baton)
+{
+ item_baton *ib = parent_baton;
+ jobject result;
+
+ /* ### python doesn't have 'const' on the method name and format */
+ if ((result = PyObject_CallMethod(ib->editor, (char *)"add_directory",
+ (char *)"sOslO&", path, ib->baton,
+ copyfrom_path, copyfrom_revision,
+ make_ob_pool, dir_pool)) == NULL)
+ {
+ return convert_python_error(dir_pool);
+ }
+
+ /* make_baton takes our 'result' reference */
+ *child_baton = make_baton(dir_pool, ib->editor, result);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_open_directory(const char *path,
+ void *parent_baton,
+ svn_revnum_t base_revision,
+ apr_pool_t *dir_pool,
+ void **child_baton)
+{
+ item_baton *ib = parent_baton;
+ jobject result;
+
+ /* ### python doesn't have 'const' on the method name and format */
+ if ((result = PyObject_CallMethod(ib->editor, (char *)"open_directory",
+ (char *)"sOlO&", path, ib->baton,
+ base_revision,
+ make_ob_pool, dir_pool)) == NULL)
+ {
+ return convert_python_error(dir_pool);
+ }
+
+ /* make_baton takes our 'result' reference */
+ *child_baton = make_baton(dir_pool, ib->editor, result);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_change_dir_prop(void *dir_baton,
+ const char *name,
+ const svn_string_t *value,
+ apr_pool_t *pool)
+{
+ item_baton *ib = dir_baton;
+ jobject result;
+
+ /* ### python doesn't have 'const' on the method name and format */
+ if ((result = PyObject_CallMethod(ib->editor, (char *)"change_dir_prop",
+ (char *)"Oss#O&", ib->baton, name,
+ value->data, value->len,
+ make_ob_pool, pool)) == NULL)
+ {
+ return convert_python_error(pool);
+ }
+
+ /* there is no return value, so just toss this object (probably Py_None) */
+ Py_DECREF(result);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_close_directory(void *dir_baton)
+{
+ return close_baton(dir_baton, "close_directory");
+}
+
+static svn_error_t * thunk_add_file(const char *path,
+ void *parent_baton,
+ const char *copyfrom_path,
+ svn_revnum_t copyfrom_revision,
+ apr_pool_t *file_pool,
+ void **file_baton)
+{
+ item_baton *ib = parent_baton;
+ jobject result;
+
+ /* ### python doesn't have 'const' on the method name and format */
+ if ((result = PyObject_CallMethod(ib->editor, (char *)"add_file",
+ (char *)"sOslO&", path, ib->baton,
+ copyfrom_path, copyfrom_revision,
+ make_ob_pool, file_pool)) == NULL)
+ {
+ return convert_python_error(file_pool);
+ }
+
+ /* make_baton takes our 'result' reference */
+ *file_baton = make_baton(file_pool, ib->editor, result);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_open_file(const char *path,
+ void *parent_baton,
+ svn_revnum_t base_revision,
+ apr_pool_t *file_pool,
+ void **file_baton)
+{
+ item_baton *ib = parent_baton;
+ jobject result;
+
+ /* ### python doesn't have 'const' on the method name and format */
+ if ((result = PyObject_CallMethod(ib->editor, (char *)"open_file",
+ (char *)"sOlO&", path, ib->baton,
+ base_revision,
+ make_ob_pool, file_pool)) == NULL)
+ {
+ return convert_python_error(file_pool);
+ }
+
+ /* make_baton takes our 'result' reference */
+ *file_baton = make_baton(file_pool, ib->editor, result);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_window_handler(svn_txdelta_window_t *window,
+ void *baton)
+{
+ handler_baton *hb = baton;
+ jobject result;
+
+ if (window == NULL)
+ {
+ /* the last call; it closes the handler */
+
+ /* invoke the handler with None for the window */
+ /* ### python doesn't have 'const' on the format */
+ result = PyObject_CallFunction(hb->handler, (char *)"O", Py_None);
+
+ /* we no longer need to refer to the handler object */
+ Py_DECREF(hb->handler);
+ }
+ else
+ {
+ /* invoke the handler with the window */
+ /* ### python doesn't have 'const' on the format */
+ result = PyObject_CallFunction(hb->handler,
+ (char *)"O&", make_ob_window, window);
+ }
+
+ if (result == NULL)
+ return convert_python_error(hb->pool);
+
+ /* there is no return value, so just toss this object (probably Py_None) */
+ Py_DECREF(result);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_apply_textdelta(
+ void *file_baton,
+ svn_txdelta_window_handler_t *handler,
+ void **h_baton)
+{
+ item_baton *ib = file_baton;
+ jobject result;
+
+ /* ### python doesn't have 'const' on the method name and format */
+ if ((result = PyObject_CallMethod(ib->editor, (char *)"apply_textdelta",
+ (char *)"O", ib->baton)) == NULL)
+ {
+ return convert_python_error(ib->pool);
+ }
+
+ if (result == Py_None)
+ {
+ Py_DECREF(result);
+ *handler = NULL;
+ *h_baton = NULL;
+ }
+ else
+ {
+ handler_baton *hb = apr_palloc(ib->pool, sizeof(*hb));
+
+ /* return the thunk for invoking the handler. the baton takes our
+ 'result' reference. */
+ hb->handler = result;
+ hb->pool = ib->pool;
+
+ *handler = thunk_window_handler;
+ *h_baton = hb;
+ }
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_change_file_prop(void *file_baton,
+ const char *name,
+ const svn_string_t *value,
+ apr_pool_t *pool)
+{
+ item_baton *ib = file_baton;
+ jobject result;
+
+ /* ### python doesn't have 'const' on the method name and format */
+ if ((result = PyObject_CallMethod(ib->editor, (char *)"change_file_prop",
+ (char *)"Oss#O&", ib->baton, name,
+ value->data, value->len,
+ make_ob_pool, pool)) == NULL)
+ {
+ return convert_python_error(pool);
+ }
+
+ /* there is no return value, so just toss this object (probably Py_None) */
+ Py_DECREF(result);
+
+ return SVN_NO_ERROR;
+}
+
+static svn_error_t * thunk_close_file(void *file_baton)
+{
+ return close_baton(file_baton, "close_file");
+}
+
+static svn_error_t * thunk_close_edit(void *edit_baton)
+{
+ return close_baton(edit_baton, "close_edit");
+}
+
+static svn_error_t * thunk_abort_edit(void *edit_baton)
+{
+ return close_baton(edit_baton, "abort_edit");
+}
+
+static const svn_delta_editor_t thunk_editor = {
+ thunk_set_target_revision,
+ thunk_open_root,
+ thunk_delete_entry,
+ thunk_add_directory,
+ thunk_open_directory,
+ thunk_change_dir_prop,
+ thunk_close_directory,
+ thunk_add_file,
+ thunk_open_file,
+ thunk_apply_textdelta,
+ thunk_change_file_prop,
+ thunk_close_file,
+ thunk_close_edit,
+ thunk_abort_edit
+};
+
+void svn_swig_java_make_editor(JNIEnv *jenv,
+ const svn_delta_editor_t **editor,
+ void **edit_baton,
+ jobject java_editor,
+ apr_pool_t *pool)
+{
+ *editor = &thunk_editor;
+ *edit_baton = make_baton(pool, java_editor, NULL);
+}
+
+/* ----------------------------------------------------------------
+ * local variables:
+ * eval: (load-file "../../../tools/dev/svn-dev.el")
+ * end:
+ */
Index: ./svn_client.i
===================================================================
--- ./svn_client.i
+++ ./svn_client.i Wed Oct 16 09:15:22 2002
@@ -98,6 +98,12 @@
}
$result = t_output_helper($result, list);
}
+%typemap(java,argout) apr_hash_t **statushash {
+ /* FIXME: Use JNI equiv of Java type SWIGTYPE_p_svn_wc_status_t */
+ $result = t_output_helper(
+ $result,
+ svn_swig_java_convert_hash(*$1, SWIGTYPE_p_svn_wc_status_t));
+}
/* -----------------------------------------------------------------------
handle the "statushash" OUTPUT param for svn_client_status()
@@ -128,6 +134,10 @@
#ifdef SWIGPYTHON
#include "swigutil_py.h"
#endif
+
+#ifdef SWIGJAVA
+#include "swigutil_java.h"
+#endif
%}
%include svn_client.h
Index: ./swigutil_java.h
===================================================================
--- ./swigutil_java.h
+++ ./swigutil_java.h Fri Oct 11 19:24:04 2002
@@ -0,0 +1,103 @@
+/*
+ * swigutil_java.h : utility functions and stuff for the SWIG Java bindings
+ *
+ * ====================================================================
+ * Copyright (c) 2000-2002 CollabNet. All rights reserved.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at http://subversion.tigris.org/license-1.html.
+ * If newer versions of this license are posted there, you may use a
+ * newer version instead, at your option.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals. For exact contribution history, see the revision
+ * history and logs, available at http://subversion.tigris.org/.
+ * ====================================================================
+ */
+
+
+#ifndef SVN_SWIG_SWIGUTIL_JAVA_H
+#define SVN_SWIG_SWIGUTIL_JAVA_H
+
+#include <jni.h>
+
+#include <apr.h>
+#include <apr_pools.h>
+#include <apr_strings.h>
+#include <apr_hash.h>
+#include <apr_tables.h>
+
+#include "svn_types.h"
+#include "svn_string.h"
+#include "svn_delta.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/* If this file is being included outside of a wrapper file, then need to
+ create stubs for some of the SWIG types. */
+
+/* if SWIGEXPORT is defined, then we're in a wrapper. otherwise, we need
+ the prototypes and type definitions. */
+#ifndef SWIGEXPORT
+#define SVN_NEED_SWIG_TYPES
+#endif
+
+#ifdef SVN_NEED_SWIG_TYPES
+
+typedef struct _unnamed swig_type_info;
+jobject *SWIG_NewPointerObj(JNIEnv *jenv, void *, swig_type_info *, int own);
+swig_type_info *SWIG_TypeQuery(JNIEnv *jenv, const char *name);
+
+#endif /* SVN_NEED_SWIG_TYPES */
+
+
+/* helper function to convert an apr_hash_t* (char* -> svnstring_t*) to
+ a Java Map */
+jobject svn_swig_java_prophash_to_dict(JNIEnv *jenv, apr_hash_t *hash);
+
+/* convert a hash of 'const char *' -> TYPE into a Java Map */
+jobject svn_swig_java_convert_hash(JNIEnv *jenv, apr_hash_t *hash,
+ swig_type_info *type);
+
+/* helper function to convert a 'char **' into a Java List of String
+ objects */
+jobject svn_swig_java_c_strings_to_list(JNIEnv *jenv, char **strings);
+
+/* helper function to convert an array of 'const char *' to a Java List of
+ String objects */
+jobject svn_swig_java_array_to_list(JNIEnv *jenv,
+ const apr_array_header_t *strings);
+
+/* helper function to convert a Java List of String objects into an
+ 'apr_array_header_t *' of 'const char *' objects. Note that the
+ objects must remain alive -- the values are not copied. This is
+ appropriate for incoming arguments which are defined to last the
+ duration of the function's execution. */
+const apr_array_header_t *svn_swig_java_strings_to_array(JNIEnv *jenv,
+ jobject source,
+ apr_pool_t *pool);
+
+/* make a editor that "thunks" from C callbacks up to Java */
+void svn_swig_java_make_editor(JNIEnv *jenv,
+ const svn_delta_editor_t **editor,
+ void **edit_baton,
+ jobject java_editor,
+ apr_pool_t *pool);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* SVN_SWIG_SWIGUTIL_JAVA_H */
+
+
+/* ----------------------------------------------------------------
+ * local variables:
+ * eval: (load-file "../../../tools/dev/svn-dev.el")
+ * end:
+ */
Index: ./util.i
===================================================================
--- ./util.i
+++ ./util.i Fri Oct 11 19:46:41 2002
@@ -189,4 +189,8 @@
#ifdef SWIGPYTHON
#include "swigutil_py.h"
#endif
+
+#ifdef SWIGJAVA
+#include "swigutil_java.h"
+#endif
%}
Index: ./svn_repos.i
===================================================================
--- ./svn_repos.i
+++ ./svn_repos.i Fri Oct 11 19:46:41 2002
@@ -62,4 +62,8 @@
#ifdef SWIGPYTHON
#include "swigutil_py.h"
#endif
+
+#ifdef SWIGJAVA
+#include "swigutil_java.h"
+#endif
%}
Index: ./svn_delta.i
===================================================================
--- ./svn_delta.i
+++ ./svn_delta.i Fri Oct 11 19:46:41 2002
@@ -82,4 +82,8 @@
#ifdef SWIGPYTHON
#include "swigutil_py.h"
#endif
+
+#ifdef SWIGJAVA
+#include "swigutil_java.h"
+#endif
%}
Index: ./apr.i
===================================================================
--- ./apr.i
+++ ./apr.i Wed Oct 16 08:15:40 2002
@@ -62,6 +62,12 @@
%typemap(python,argout,fragment="t_output_helper") apr_time_t * {
$result = t_output_helper($result, PyLong_FromLongLong(*$1));
}
+%typemap(java,argout) apr_time_t * {
+ jclass cls = JCALL1(FindClass, jenv, "java/lang/Long");
+ jmethodID ctor = JCALL3(GetMethodID, jenv, cls, "<init>", "(J)V");
+ jobject l = JCALL3(NewObject, jenv, cls, ctor, (jlong) *$1);
+ $result = t_output_helper($result, JCALL1(NewGlobalRef, jenv, l));
+}
/* -----------------------------------------------------------------------
create some INOUT typemaps for apr_size_t
@@ -73,6 +79,12 @@
temp = (apr_size_t) PyInt_AsLong($input);
$1 = &temp;
}
+%typemap(java,in) apr_size_t *INOUT (apr_size_t temp) {
+ jclass cls = JCALL1(FindClass, jenv, "java/lang/Long");
+ jmethodID mid = JCALL3(GetStaticMethodID, jenv, cls, "longValue", "()J");
+ temp = (apr_size_t) JCALL2(CallStaticLongMethod, jenv, mid, $input);
+ $1 = &temp;
+}
/* -----------------------------------------------------------------------
create an OUTPUT argument typemap for an apr_hash_t **
@@ -93,6 +105,12 @@
Py_DECREF($result);
$result = svn_swig_py_prophash_to_dict(*$1);
}
+%typemap(java,argout) apr_hash_t **PROPHASH {
+ /* toss prior result, get new result from the hash */
+ JCALL1(DeleteGlobalRef, jenv, $result);
+ $result = JCALL1(NewGlobalRef, jenv,
+ svn_swig_java_prophash_to_dict(jenv, *$1));
+}
/* -----------------------------------------------------------------------
apr_file_t ** is always an OUT param
@@ -105,6 +123,13 @@
$result = t_output_helper(
$result,
SWIG_NewPointerObj(*$1, $*1_descriptor, 0));
+}
+%typemap(java,argout) apr_file_t ** {
+ /* HELP: Is there a JNI equivalent of SWIG_NewPointerObj, or is
+ this actually a cross-language typemap? */
+ $result = t_output_helper(
+ $result,
+ SWIG_NewPointerObj(*$1, $*1_descriptor, 0));
}
/* ----------------------------------------------------------------------- */
Index: ./Makefile
===================================================================
--- ./Makefile
+++ ./Makefile Wed Oct 16 09:14:06 2002
@@ -0,0 +1,15 @@
+# TODO: Use -swiglig argument to avoid the need for SWIG-internal paths.
+SWIG_CMD=/usr/local/swig/bin/swig -c -java -noproxy -module 'svn_jni' -I'.' -I'../../include' -I'/home/dlr/src/apache.org/apr/include' -I'/usr/local/swig/lib/swig1.3' -I'/usr/local/swig/lib/swig1.3/java'
+
+build-java: swig-java
+
+swig-java:
+ for source in *.i; do \
+ target="`echo -n $$source | perl -pe 's/..$$/.jni.c/'`"; \
+ $(SWIG_CMD) -o $$target $$source; \
+ done; unset target source
+
+clean: swig-java-clean
+
+swig-java-clean:
+ rm -f *.jni.c *.java
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Re: SWIG Java bindings
Posted by cm...@collab.net.
Morten Ludvigsen <mo...@yahoo.co.uk> writes:
> Is anyone actively working on SWIG-Java bindings?
I don't think anyone has *ever* worked on our SWIG/Java bindings.
> If not I think I will take a crack at it :-)
Sweet! We'll look forward to you patches.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org