Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The simplest solution is to <a href="https://stackoverflow.com/a/10495755/168175">use SWIG's <code>&lt;carrays.i&gt;</code> to make a type that wraps an array</a> of <code>float</code> and an array of <code>int</code> and any other types you care about. These can be converted to <code>SWIGTYPE_p_float</code> etc. trivially using the <code>cast()</code> member function. The problem is that this can't automatically be converted to a <code>SWIGTYPE_p_void</code> from within Java. You could in theory call:</p> <pre><code>new SWIGTYPE_p_void(FloatArray.getCPtr(myfloatarr)); </code></pre> <p>but for various reasons (not least it's cumbersome) that's less than ideal. (It also has issues with memory ownership and garbage collection).</p> <p>So instead I defined an interface:</p> <pre><code>public interface VoidPtr { public long asVoidPtr(); } </code></pre> <p>That we can make the wrapped version of your library take as input and the array classes <code>FloatArray</code>, <code>IntArray</code> etc. implement for us.</p> <p>This ends up with the module file:</p> <pre><code>%module test %include &lt;carrays.i&gt; %typemap(javainterfaces) FloatArray "VoidPtr" %typemap(javainterfaces) IntArray "VoidPtr" %typemap(javacode) FloatArray %{ public long asVoidPtr() { return getCPtr(this); } %} %typemap(javacode) IntArray %{ public long asVoidPtr() { return getCPtr(this); } %} %array_class(float, FloatArray); %array_class(int, IntArray); %typemap(jstype) void *arr "VoidPtr" %typemap(javain) void *arr "$javainput.asVoidPtr()" void foo(void *arr); </code></pre> <p>Which modifies <code>void *arr</code> to be treated as our <code>VoidPtr</code> type and automatically calls the <code>asVoidPtr()</code> method. You could use <a href="http://www.swig.org/Doc1.3/Typemaps.html#Typemaps_nn13" rel="nofollow noreferrer">typemap copying</a> or macros to make this less repetitive. (Note, there's a possible issue with <a href="http://www.swig.org/Doc1.3/Java.html#java_pgcpp" rel="nofollow noreferrer">premature garbage collection</a> that might need to be addressed here depending on how you planned to use this)</p> <p>This allows us to write code like:</p> <pre><code>public class run { public static void main(String[] argv) { FloatArray arr = new FloatArray(100); test.foo(arr); } } </code></pre> <p>I think this is the easiest, cleanest solution. There are several other ways you could solve this though:</p> <ol> <li><p>It's also possible to write some code that would take an actual Java array rather than just the SWIG <code>array_class</code> and implement this interface by calling a JNI function to obtain the underlying pointer. You'd have to write a version of this for every primitive type though, just like the above.</p> <p>An interface file could then look something like:</p> <pre><code>%module test %{ void foo(void *arr); %} %typemap(in,numinputs=0) JNIEnv *env "$1 = jenv;" %rename(foo) fooFloat; %rename(foo) fooInt; %inline %{ void fooFloat(JNIEnv *env, jfloatArray arr) { jboolean isCopy; foo((*env)-&gt;GetFloatArrayElements(env, arr, &amp;isCopy)); // Release after call with desired semantics } void fooInt(JNIEnv *env, jintArray arr) { jboolean isCopy; foo((*env)-&gt;GetIntArrayElements(env, arr, &amp;isCopy)); // Release after call } %} void foo(void *arr); </code></pre> <p>Which then gives you overloads of <code>foo</code> which take <code>float[]</code> and <code>int[]</code> as well as <code>SWIGTYPE_p_void</code>.</p></li> <li><p>You could use a trick with a union:</p> <pre><code>%inline %{ union Bodge { void *v; float *f; int *i; }; %} </code></pre> <p>although this is considered bad form, it does generate you a Java interface that can be used to convert from <code>SWIGTYPE_p_int</code> to <code>SWIGTYPE_p_void</code>.</p></li> <li><p>I think it's possible to make <code>FloatArray</code> inherit from <code>SWIGTYPE_p_void</code>, something like the following compiled but untested code:</p> <pre><code>%module test %include &lt;carrays.i&gt; %typemap(javabase) FloatArray "SWIGTYPE_p_void" %typemap(javabody) FloatArray %{ private long swigCPtr; // Minor bodge to work around private variable in parent private boolean swigCMemOwn; public $javaclassname(long cPtr, boolean cMemoryOwn) { super(cPtr, cMemoryOwn); this.swigCPtr = SWIGTYPE_p_void.getCPtr(this); swigCMemOwn = cMemoryOwn; } %} %array_class(float, FloatArray); void foo(void *arr); </code></pre> <p>This duplicates the pointer on the Java side, but nothing changes that (currently) in either the void pointer or array classes so that's not as big a problem as it first seems. (You could also make it protected in the base class with an alternative typemap I think, or use a modified version of <code>carrays.i</code> that gets <code>swigCPtr</code> via the <code>getCPtr</code> function instead)</p></li> </ol>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload