4

I recently found the library UnmanagedExports that allowed me to access C#-methods directly from Java using JNA.

Has anyone an idea about what is wrong with my attempt to return a byte array from C# to Java?

Here is my example:

C# code:

using System;
using RGiesecke.DllExport;
namespace JnaTestLibrary
{
  public class JnaTest
  {
    [DllExport]
    public static byte[] returnT1()
    {
        byte[] t1 = {1,2,3,4,5};
        return t1;
    }
  }
}

Java code:

package me.mt.test;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
public class JnaTest {
  public interface JnaTestInterface extends Library{
      byte[] returnT1();
  }
  static JnaTestInterface jnaTest = null;

  static{       
        if(Platform.is64Bit()){
            jnaTest = (JnaTestInterface)Native.loadLibrary("JnaTestLibrary64", JnaTestInterface.class);
        }
        else{
            jnaTest = (JnaTestInterface)Native.loadLibrary("JnaTestLibrary86", JnaTestInterface.class);
        }
    }

  public byte[] returnT1(){
      return jnaTest.returnT1();
  }
}

Java exception:

Exception in thread "main" java.lang.IllegalArgumentException: Unsupported return type class [I in function returnT1
1
  • I do not know a lot about jna, but I believe that ByteBuffers (specifically the direct variant) can be used to pass byte arrays across native boundaries. Commented Dec 30, 2014 at 21:54

1 Answer 1

1

I solved the problem by using pointers.

C# code:

using System;
using RGiesecke.DllExport;
namespace JnaTestLibrary
{
  public class JnaTest
  {
    [DllExport]
    public unsafe static byte* returnT1()
    {
        byte[] t1 = {1,2,3,4,5};
        fixed (byte* p1 = t1)
        {
          return p1;
        }
    }
  }
}

Java code:

package me.mt.test;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import com.sun.jna.Pointer;
public class JnaTest {
  public interface JnaTestInterface extends Library{
      Pointer returnT1();
  }
  static JnaTestInterface jnaTest = null;

  static{       
        if(Platform.is64Bit()){
            jnaTest = (JnaTestInterface)Native.loadLibrary("JnaTestLibrary64", JnaTestInterface.class);
        }
        else{
            jnaTest = (JnaTestInterface)Native.loadLibrary("JnaTestLibrary86", JnaTestInterface.class);
        }
    }

  public byte[] returnT1(){
      Pointer p1 = jnaTest.returnT1();
      return p1.getByteArray(0, 5);
  }
}
Sign up to request clarification or add additional context in comments.

3 Comments

I think the pointed-to data could get clobbered by a CLR garbage collection between jnaTest.returnT1() and p1.getByteArray(0, 5).
@TomBlodget The unsafe keyword doesn't change the semantics of ordinary code at all. Until now everything works fine.
You're banking on luck. See this answer. The basic problem is memory ownership and, depending on the technique, transfer of ownership. You are using memory after giving ownership back to the CLR—outside the scope of the fixed statement.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.