How can I hide some parameters from C DLL function on JNA Wrapper side? - jna

I've successfully wrapped a C DLL library using JNA.
As I'm not the owner of the C development part, I would like to hide
some parameters of a C function that I've wrapped on java side.
To be more precise my java code is as follows :
public interface IJNALibrary extends Library {
// INIT FUNCTION
public int initFunction(int firstValue, int secondValue, int thirdValue);
}
On the C side I have in the *.h file :
extern "C" CSAMPLE_API int initFunction (
unsigned firstValue,
unsigned secondValue,
unsigned thirdValue);
My purpose is to directly set secondValue and thirdValue parameters to 1 and thus hide those parameters to the java API user.
I don't want the user to know that he could change the values of those parameters.
In fact I would like to have something like :
public interface IJNALibrary extends Library {
// INIT FUNCTION
public int initFunction(int firstValue);
}
and initFunction(int firstValue) calls initFunction(int firstValue, int secondValue, int thirdValue) from the C DLL part.
But this has to be done inside the java Wrapper and not from the code which calls the java Wrapper.
I'm afraid that It cannot be possible, is it?
Unless I create another C DLL (with public int initFunction(int firstValue) function) which calls the first C DLL(which embed initFunction(int firstValue, int secondValue, int thirdValue).But I would rather do it on the java side in order not to have manage 2 C DLLs.
See also below the Sample.java file which calls the mapped method defined in IJNALibrary interface.
public class Sample {
static IJNALibrary IJNAFunctions;
public static void main(String[] args) throws IOException {
System.setProperty("jna.library.path", "./librayPath");
// LOADING LIBRARY
IJNAFunctions = (IJNALibrary) Native.load("c", IJNALibrary.class);
int firstValue = 1;
int secondValue = 2;
int thirdValue = 3;
int initReturn = IJNAFunctions.initFunction(firstValue, secondValue, thirdValue);
}
}
Thanx for your help.

It depends on what you want to archive. If you want to make it easier for users to call the init, this is an option (demonstrated using gethostname from libc), which uses a Java 8 feature, which allows adding default methods to interfaces:
public class TestDefaultMethod {
public static interface LibC extends Library {
LibC INSTANCE = Native.load("c", LibC.class);
// Original binding of method
int gethostname(byte[] name, int len);
// Helper method to make it easier to call gethostname
default String gethostname() {
byte[] result = new byte[255];
LibC.INSTANCE.gethostname(result, result.length);
return Native.toString(result);
}
}
public static void main(String[] args) {
// Usage
System.out.println(LibC.INSTANCE.gethostname());
}
}
Java developers normally don't arrays to functions, which fill them and a java developer would never pass the length of the array in a separate parameter. These are artifacts of the C nature of the function. In the wrapped function an array is allocated, the native call done and the array then unwrapped. All the ugly C specialties are hidden in the default method.
If you don't want to expose the method on java at all (be warned, if your users can access the JNA library, they can circumvent your protections!), you can use a function pointer directly:
public class TestDefaultMethod {
public static interface LibC extends Library {
NativeLibrary libc = NativeLibrary.getInstance("c");
LibC INSTANCE = Native.load("c", LibC.class);
default String gethostname() {
byte[] result = new byte[255];
libc.getFunction("gethostname").invokeInt(new Object[] {result, result.length});
return Native.toString(result);
}
}
public static void main(String[] args) {
System.out.println(LibC.INSTANCE.gethostname());
}
}
Same idea as above, the default method will hide the ugly parts. In this case though the function is not accessed through the managed INSTANCE, but access through the function pointer directly.

Related

Is it possible to access OpenGL ES from RoboVM without using LibGDX?

Is it possible to access OpenGL ES on iOS from RoboVM without using LibGDX? If so, are there any useful references?
The only thing I can find is this super-simple demo from over 2 years ago: http://robovm.com/ios-opengles-in-java-on-robovm/
But it doesn't provide any functions besides glClearColor and glClear.
The Apple GLKit framework seems to be implemented, though. I just can't find all the actual glWhatever(...) functions...
Yes, it is possible. You need two things for this: 1. Access to the OpenGL ES functions (like glClear(...), etc.) and 2. a UIView in your app that can draw the GL image.
Turns out the second point is very easy. You can either use a GLKView (requires iOS 5.0) or a CAEAGLLayer (requires iOS 2.0) if you're feeling nostalgic. For both, there are tons of tutorials online on how to use them in Objective-C, which can readily be translated to RoboVM. So, I won't spend too much time on this point here.
Access to the OpenGL ES functions is a little more difficult, as RoboVM doesn't ship with the definitions file out of the box. So, we'll have to build our own using Bro. Turns out, once you wrap your head around how Bro handles C-strings, variable pointers, IntBuffers and such (which is actually quite beautiful!), it's really pretty straight forward. The super-simple demo I linked to in the original question is the right starting point.
In the interest of brevity, let me post here just a very abridged version of the file I wrote to illustrate the way the different data types can be handled:
import java.nio.Buffer;
import java.nio.IntBuffer;
import org.robovm.rt.bro.Bro;
import org.robovm.rt.bro.Struct;
import org.robovm.rt.bro.annotation.Bridge;
import org.robovm.rt.bro.annotation.Library;
import org.robovm.rt.bro.ptr.BytePtr;
import org.robovm.rt.bro.ptr.BytePtr.BytePtrPtr;
import org.robovm.rt.bro.ptr.IntPtr;
#Library("OpenGLES")
public class GLES20 {
public static final int GL_DEPTH_BUFFER_BIT = 0x00000100;
public static final int GL_STENCIL_BUFFER_BIT = 0x00000400;
public static final int GL_COLOR_BUFFER_BIT = 0x00004000;
public static final int GL_FALSE = 0;
public static final int GL_TRUE = 1;
private static final int MAX_INFO_LOG_LENGTH = 10*1024;
private static final ThreadLocal<IntPtr> SINGLE_VALUE =
new ThreadLocal<IntPtr>() {
#Override
protected IntPtr initialValue() {
return Struct.allocate(IntPtr.class, 1);
}
};
private static final ThreadLocal<BytePtr> INFO_LOG =
new ThreadLocal<BytePtr>() {
#Override
protected BytePtr initialValue() {
return Struct.allocate(BytePtr.class, MAX_INFO_LOG_LENGTH);
}
};
static {
Bro.bind(GLES20.class);
}
#Bridge
public static native void glClearColor(float red, float green, float blue, float alpha);
#Bridge
public static native void glClear(int mask);
#Bridge
public static native void glGetIntegerv(int pname, IntPtr params);
// DO NOT CALL THE NEXT METHOD WITH A pname THAT RETURNS MORE THAN ONE VALUE!!!
public static int glGetIntegerv(int pname) {
IntPtr params = SINGLE_VALUE.get();
glGetIntegerv(pname, params);
return params.get();
}
#Bridge
private static native int glGetUniformLocation(int program, BytePtr name);
public static int glGetUniformLocation(int program, String name) {
return glGetUniformLocation(program, BytePtr.toBytePtrAsciiZ(name));
}
#Bridge
public static native int glGenFramebuffers(int n, IntPtr framebuffers);
public static int glGenFramebuffer() {
IntPtr framebuffers = SINGLE_VALUE.get();
glGenFramebuffers(1, framebuffers);
return framebuffers.get();
}
#Bridge
private static native void glShaderSource(int shader, int count, BytePtrPtr string, IntPtr length);
public static void glShaderSource(int shader, String code) {
glShaderSource(shader, 1, new BytePtrPtr().set(BytePtr.toBytePtrAsciiZ(code)), null);
}
#Bridge
private static native void glGetShaderInfoLog(int shader, int maxLength, IntPtr length, BytePtr infoLog);
public static String glGetShaderInfoLog(int shader) {
BytePtr infoLog = INFO_LOG.get();
glGetShaderInfoLog(shader, MAX_INFO_LOG_LENGTH, null, infoLog);
return infoLog.toStringAsciiZ();
}
#Bridge
public static native void glGetShaderPrecisionFormat(int shaderType, int precisionType, IntBuffer range, IntBuffer precision);
#Bridge
public static native void glTexImage2D(int target, int level, int internalformat, int width, int height, int border, int format, int type, IntBuffer data);
#Bridge
private static native void glVertexAttribPointer(int index, int size, int type, int normalized, int stride, Buffer pointer);
public static void glVertexAttribPointer(int index, int size, int type, boolean normalized, int stride, Buffer pointer) {
glVertexAttribPointer(index, size, type, normalized ? GL_TRUE : GL_FALSE, stride, pointer);
}
}
Note how most methods are exposed via just trivial #Bridge-annotated native definitions, but for some it's convenient to define a wrapper method in Java that converts a String to a *char or unpacks a result from an IntPtr for example.
I didn't post my whole library file, since it is still very incomplete and it'll just make it harder to find the examples of how different parameter types are handled.
To save yourself some work, you can copy the GL constant definitions from libGDX's GL20.java. And the OpenGL ES docs are a great reference for the calling signature of the methods (the data types GLenum and GLbitfield correspond to a Java int).
You can then call the gl-methods statically by prepending GLES20. (just like on Android), e.g.:
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
Turns out Bro is so smart that you don't even need to include the <framework>OpenGLES</framework> tag in robovm.xml any more, like you would with libGDX.
And - What do you know? - my app starts about 3 times as quickly as it did when it was still using libGDX. And it fixed another issue I had (see LibGDX displays black screen while app is paused but still visible (e.g. during in-app purchase password dialog) on iOS). "Yay!" for getting rid of unnecessary baggage.
The one thing that makes life a little annoying is that if you mess up the call signature of a method or the memory allocation, your app will simply crash with a very unhelpful "Terminated due to signal 11" message in the IDE-console that contains no information about where the app died.

Dependency Injection of Primitive Types (Decided at Runtime) With HK2

So basically, I have a situation where I want to inject primitive types into a class (i.e. a String and an Integer). You can think of a URL and port number for an application as example inputs. I have three components:
Now say I have a class, which does take in these params:
public class PrimitiveParamsDIExample {
private String a;
private Integer b;
public PrimitiveParamsDIExample(String a, Integer b) {
this.a = a;
this.b = b;
}
}
So my question here is simple. How do I inject a and b into class PrimitiveParamsDIExample?
In general, this is also asking how to inject parameters that are decided on runtime as well. If I have a and b above, read from STDIN or from an input file, they're obviously going to be different from run to run.
All the more, how do I do the above within the HK2 framework?
EDIT[02/23/15]: #jwells131313, I tried your idea, but I'm getting the following error (this one for the String param; similar one for int):
org.glassfish.hk2.api.UnsatisfiedDependencyException: There was no object available for injection at Injectee(requiredType=String,parent=PrimitiveParamsDIExample,qualifiers
I set up classes exactly as you did in your answer. I also overrode the toString() method to print both variables a and b in PrimitiveParamsDIExample. Then, I added the following in my Hk2Module class:
public class Hk2Module extends AbstractBinder {
private Properties properties;
public Hk2Module(Properties properties){
this.properties = properties;
}
#Override
protected void configure() {
bindFactory(StringAFactory.class).to(String.class).in(RequestScoped.class);
bindFactory(IntegerBFactory.class).to(Integer.class).in(RequestScoped.class);
bind(PrimitiveParamsDIExample.class).to(PrimitiveParamsDIExample.class).in(Singleton.class);
}
}
So now, I created a test class as follows:
#RunWith(JUnit4.class)
public class TestPrimitiveParamsDIExample extends Hk2Setup {
private PrimitiveParamsDIExample example;
#Before
public void setup() throws IOException {
super.setupHk2();
//example = new PrimitiveParamsDIExample();
example = serviceLocator.getService(PrimitiveParamsDIExample.class);
}
#Test
public void testPrimitiveParamsDI() {
System.out.println(example.toString());
}
}
where, Hk2Setup is as follows:
public class Hk2Setup extends TestCase{
// the name of the resource containing the default configuration properties
private static final String DEFAULT_PROPERTIES = "defaults.properties";
protected Properties config = null;
protected ServiceLocator serviceLocator;
public void setupHk2() throws IOException{
config = new Properties();
Reader defaults = Resources.asCharSource(Resources.getResource(DEFAULT_PROPERTIES), Charsets.UTF_8).openBufferedStream();
load(config, defaults);
ApplicationHandler handler = new ApplicationHandler(new MyMainApplication(config));
final ServiceLocator locator = handler.getServiceLocator();
serviceLocator = locator;
}
private static void load(Properties p, Reader r) throws IOException {
try {
p.load(r);
} finally {
Closeables.close(r, false);
}
}
}
So somewhere, the wiring is messed up for me to get an UnsatisfiedDependencyException. What have I not correctly wired up?
Thanks!
There are two ways to do this, but one isn't documented yet (though it is available... I guess I need to work on documentation again...)
I'll go through the first way here.
Basically, you can use the HK2 Factory.
Generally when you start producing Strings and ints and long and scalars like this you qualify them, so lets start with two qualifiers:
#Retention(RUNTIME)
#Target( { TYPE, METHOD, FIELD, PARAMETER })
#javax.inject.Qualifier
public #interface A {}
and
#Retention(RUNTIME)
#Target( { TYPE, METHOD, FIELD, PARAMETER })
#javax.inject.Qualifier
public #interface B {}
then write your factories:
#Singleton // or whatever scope you want
public class StringAFactory implements Factory<String> {
#PerLookup // or whatever scope, maybe this checks the timestamp?
#A // Your qualifier
public String provide() {
// Write your code to get your value...
return whatever;
}
public void dispose(String instance) {
// Probably do nothing...
}
}
and for the Integer:
#Singleton // or whatever scope you want
public class IntegerBFactory implements Factory<Integer> {
#PerLookup // or whatever scope, maybe this checks the timestamp?
#B // Your qualifier
public Integer provide() {
// Write your code to get your value...
return whatever;
}
public void dispose(String instance) {
// Probably do nothing...
}
}
Now lets re-do your original class to accept these values:
public class PrimitiveParamsDIExample {
private String a;
private int b;
#Inject
public PrimitiveParamsDIExample(#A String a, #B int b) {
this.a = a;
this.b = b;
}
}
Note I changed Integer to int, well... just because I can. You can also just use field injection or method injection in the same way. Here is field injection, method injection is an exercise for the reader:
public class PrimitiveParamsDIExample {
#Inject #A
private String a;
#Inject #B
private int b;
public PrimitiveParamsDIExample() {
}
}
There are several ways to bind factories.
In a binder: bindFactory
Using automatic class analysis: addClasses
An EDSL outside a binder: buildFactory

jna: pass a string from C# to Java

I am using Unamanged dependencies (RGiesecke.DllExport.DllExport) and jna in a small C# function that should return a string consumed within another now java function.
Following the jna suggestions for mapping i crafted the code below:
My C# code:
[RGiesecke.DllExport.DllExport]
public static unsafe char* Test(string id)
{
unsafe
{
fixed (char *s = "test passed")
{
return s;
}
}
}
Java side:
public interface ITest extends Library{
public String Test(String id);
}
public static void main(String[] args) {
ITest nativeExample= (ITest)Native.loadLibrary("C:/native/JavaLib.dll", ITest.class);
String s = nativeExample.Test("id");
System.out.println(s);
}
So, all that is printed, is 't', because I bet all is being transmitted is the address to s[0].
Has anyone had luck mapping strings from C# to java through jna?
Plain strings in the C# code throws errors.
Have you tried returning a string instead of char? or changing char *s to char s[]

Can the free_function be a static class method?

This is a follow-up question to How to write void pointer typedefs in vapi files?
I now have four almost identical [Compact] classes that represent handles allocated with unixODBCs SQLAllocHandle function.
The first one (for the ENV type handle) looks like this:
[CCode (cname = "void", free_function = "EnvironmentHandle.free")]
[Compact]
public class EnvironmentHandle {
[CCode (cname = "SQLAllocHandle")]
private static Return allocate_internal (HandleType type, void* nothing, out EnvironmentHandle output_handle);
public static Return allocate (out EnvironmentHandle output_handle) {
return allocate_internal (HandleType.ENV, null, out output_handle);
}
[CCode (cname = "SQLFreeHandle")]
private static Return free_internal (HandleType type, EnvironmentHandle handle);
public static Return free (EnvironmentHandle handle) {
return free_internal (HandleType.ENV, handle);
}
}
This doesn't compile.
Is it possible to use a static class method as the free_function?
If not, is there at least a way to write a custom free_function in the vapi file?
I need a custom function because the SQLFreeHandle function takes the handle type and the handle as an argument.
From the vapi users perspective all that is really important is:
[CCode (cname = "void")]
[Compact]
public class EnvironmentHandle {
public static Return allocate (out EnvironmentHandle output_handle);
}
The only other solution would be to use a [SimpleType] struct as suggested by apmasell in the original question. That would hide the fact that a SQLHANLDE is really a reference type.
The full code of my current implementation is available online:
https://github.com/antiochus/unixodbc-vala/tree/0486f54dc3f86d9c8bf31071980e4f171aca9591
No. The free_function is a C function, not a Vala function and it cannot take any context. You have two options:
Write a C macro in an extra header file to do what you want and bind the macro as the free function.
Bind the free function as a static method that takes an owned instance of the object:
[CCode (cname = "SQLFreeHandle")]
public static Return free(HandleType type, owned EnvironmentHandle handle);
EnvrionmentHandle foo = ...;
EnvironmentHandle.free(HandleType.ENV, (owned) foo);

How does one obtain data that has been returned from a method? (Java)

This might be a really stupid question but what happens to data that is returned from a method? For example, if I have a method that adds two numbers and I tell it to return the sum, how would I access that information from the place where the method was called?
Assuming your question is related with java.
You could assign the whole method to a new variable.
public class Test {
public static void main(String args[]){
int value1=2;
int value2=5;
int sum=sum(value1,value2);
System.out.println("The sum is :"+ sum);
}
public static int sum(int value1,int value2){
return value1+value2;
}
}
What is actually happening, is that the method signature sum(value1,value2) holds the result of the 2 numbers summation. There is also another way of writing the code inside the method but the result will be the same.
For example:
public class Test {
public static void main(String args[]){
int sum=sum(2,5);
System.out.println("The sum is :"+ sum);
}
public static int sum(int value1,int value2){
int sum=value1+value2;
return sum;
}
}
P.S. You could try to use the above samples directly. They will compile and run.
In most languages, you access the result of a function by putting the function call on the right hand side of an assignment expression.
For example, in Python, you can assign the result of calling the built-in len function on a list to a variable called x by doing the following:
x = len([1, 2, 3])

Resources