Method of binding Java functions to Lua? - java

I'm working on a Lua wrapper for my Android app, which will allow me to write Lua code to speed up development. I've made a static class called lua with functions like newState and pushString. I manage the Lua state by passing around a long with the pointer to the lua_State. As you can tell, I don't need any fancy stuff that makes interaction easier, like overloads to push variables.
Now, the problem is binding Java functions to Lua variables. I've thought of a few ways to do this, but they're all ugly.
Instead of functions, pass around a table with a reference to the Java function as a userdatum and have a __call metamethod take care of calling the "function".
Alter Lua internals to include a Java reference with Lua C functions.
Is there any better way to go about this? Or should I go with the second method? (I realise the first method is ridiculous, but it manifested itself in my mind as a solution anyways.)

You can have a look at my simple project AndroLua. It contains Lua and LuaJava compiled using the Android NDK.
Because it uses LuaJava, it allows to bind Java functions to Lua, in a similar way like you said, using userdata. Here is an example of how I override the print function to output text into a TextView:
JavaFunction print = new JavaFunction(L) {
#Override
public int execute() throws LuaException {
StringBuilder sb = new StringBuilder();
for (int i = 2; i <= L.getTop(); i++) {
int type = L.type(i);
String val = L.toString(i);
if (val == null)
val = L.typeName(type);
sb.append(val);
sb.append("\t");
}
sb.append("\n");
status.append(sb.toString());
return 0;
}
};
print.register("print");
The downside is that sometimes you cannot pass the print as a function parameter (because it is a userdata, even though it has a __call metamethod). Fortunately, it can be solved in Lua by creating a pure Lua function, like this:
do
local oldprint = print
function print(...) oldprint(...) end
end

I decided to use lua_pushcclosure, as it allows you to 'store' arbitrary values on functions that can be retrieved with the lua_upvalueindex macro.

There is also Kahlua vs LuaJava.
It is mentioned in this book: http://books.google.com/books?id=2v55tfq9rosC&lpg=PA166&ots=9RRVaz5JjP&dq=krka%20kahlua%20blog&pg=PA166#v=onepage&q&f=false
The development blog:
http://krkadev.blogspot.com/2010/05/getting-started-with-kahlua2.html

Related

Modifying Java Methods/Bytecode in Runtime with C++

me and a friend of mine are working on a coding project and we ran into a little issue. We are essentially trying to modify Java Methods/Bytecode during runtime using C++. I am just curious if this is possible or how it is possible. We have already tried using JVMTI and JNI to accomplish this but it seems that you can only modify classes that are currently being loaded into the JVM. We are loading our code in as a DLL while the process is running so we can not do this. We also thought assembly might work by accomplishing this. A little demonstration of what we are trying to do can be seen below.
public boolean Method()
{
boolean value = true;
return value; //<- Value that we want to modify (in java)
}
jclass JVMUtilities::getClass(std::string clazzname) {
jstring name = Wrapper::getJVMHook().getJNI()->NewStringUTF(clazzname.c_str());
jobject classLoader = getclassloader();
jmethodID mid = Wrapper::getJVMHook().getJNI()->GetMethodID(Wrapper::getJVMHook().getJNI()->GetObjectClass(classLoader), "findClass", "(Ljava/lang/String;)Ljava/lang/Class;");
return (jclass)Wrapper::getJVMHook().getJNI()->CallObjectMethod(classLoader, mid, name);
//This is the function we use for geting the class information in c++ including location
}
Basically going by above, we want to change the return value to what we want during run time by manipulating the byte code.
There is a public standard API to do this - JVM TI RedefineClasses and RetransformClasses.

Pass C++ object to Java vs set object parameters one by one using JNI

I have searched for this question and found a few answers but have not really found what I am looking for.
I call Java using JNI from C++ and set a Java object's fields one by one. Something like below:
jobject jSomeObject = (jobject) JVM_ENV->CallObjectMethod(myObj, getObjMethodID, "");
JVM_ENV->CallVoidMethod(jSomeObject , setMethodID1, SomeIntVal);
JVM_ENV->CallVoidMethod(jSomeObject , setMethodID2, SomeStringVal);
All parameters inside the jSomeObject are set one by one like this. And you see that there are multiple JNI calls going on which is expensive. What I am thinking is, if there is a way that I set all the parameters in the native environment and send the object just once to avoid multiple JNI calls.
Some of the posts says that it is not possible to pass a custom object to JNI. Can I do it ?
Edit:
Above calls changed to something:
jobject jSomeObject = (jobject) JVM_ENV->CallObjectMethod(myObj, getObjMethodID, "");
someClass obj = new someClass();
obj.setMethod1(someInvVal);
obj.setMethod2(someStringVal); // so on...
JVM_ENV->CallVoidMethod(jSomeObject , setMethodID1, obj);
No: You can only call methods and constructors and get and set fields that are defined in Java.
Yes: You can possibly define additional classes and methods in Java that will do what you need in one call. For example, myObj:getObjMethodID seems to be a factory method. You could add a method overload that takes all the values you want to initialize the created object with.
In general, if you can make things powerful in Java, the tasks done in JNI will be simpler.

Anonymous functions similar to creating objects instead of methods?

While studying Lambda expressions for Java SE 8 I came across the following text in a studybook:
Languages that support functional programming concepts have the
ability to create anonymous (unnamed) functions, similar to creating
objects instead of methods in Java.
I am completely lost, can someone explain what the author meant here? What's the similarity? How do they compare?
The wording seems particularly clumsy and I'm not entirely sure what it's trying to say. But one thing I do take from it is this notion of functions being similar to objects, in that new functions can be created on-the-fly, and functions can contain state. This is something that other languages have had for some time, but in Java it was so cumbersome as to be impractical until Java 8, with the introduction of lambdas.
Here's a JavaScript example that creates a function that has captured some state, and that modifies this state every time it's called:
function appender (str) {
return function (s1) {
str += s1
return str
}
}
jjs> var a1 = appender("foo")
jjs> var a2 = appender("bar")
jjs> a1("x")
foox
jjs> a1("y")
fooxy
jjs> a2("qq")
barqq
(I used Nashorn jjs for this, but other JavaScript implementations should work similarly.)
You can do something similar in Java as follows:
UnaryOperator<String> appender(String str) {
StringBuilder sb = new StringBuilder(str);
return s1 -> sb.append(s1).toString();
}
UnaryOperator<String> a1 = appender("foo");
UnaryOperator<String> a2 = appender("bar");
System.out.println(a1.apply("x"));
System.out.println(a1.apply("y"));
System.out.println(a2.apply("qq"));
The output is the same:
foox
fooxy
barqq
The Java code is more verbose, mainly because of the type declarations and things like System.out.println. And the return value isn't really a function, it's an instance of a functional interface. But the essential features are the same. And once you get used to it, you really start treating instances of functional interfaces just like functions.
Of course, it was always possible to do something like this in Java 7 or earlier, with anonymous inner classes instead of lambdas, but it was so cumbersome that virtually nobody ever thought about doing things this way.
I believe the author may have meant that functional programming allows functions to have the same status as objects in java - i.e. they can stand on their own, without being part of a class (unlike methods in Java).

Java C++ Wrapper for Android: how to wrap c++ templates

I'm working on an android project (a 3d realtime application) and would like to use a c++ library I've written. Since it's relying on templates I'm looking for a good solution to write a Java wrapper around it.
One idea I had, was to include the java class name in the JNI call when I create an object. For example I instantiate a Java class like this:
//java
A a = new A(Integer.class());
//jni call
if(strcmp("java.lang.integer", className) == 0) return (jlong) new A<int>();
else if(strcmp("java.lang.float", className) == 0) return (jlong) new A<float>();
else if( .... )
The problem with this solution is, that whenever I want to use a new data type I have to add another elseif code block and compile the c++ code again.
The problem with this solution is, that whenever I want to use a new data type I have to add another elseif code block.
Remember that there are only 8 primitive types in Java. If you add one if-else for each of those, you will be able to handle any primitive type argument.
If you also add a case for jobject you can also use that to handle any object type. Just be careful to handle your JNI object references correctly.

Java replacement for C macros

Recently I refactored the code of a 3rd party hash function from C++ to C. The process was relatively painless, with only a few changes of note. Now I want to write the same function in Java and I came upon a slight issue.
In the C/C++ code there is a C preprocessor macro that takes a few integer variables names as arguments and performs a bunch of bitwise operations with their contents and a few constants. That macro is used in several different places, therefore its presence avoids a fair bit of code duplication.
In Java, however, there is no equivalent for the C preprocessor. There is also no way to affect any basic type passed as an argument to a method - even autoboxing produces immutable objects. Coupled with the fact that Java methods return a single value, I can't seem to find a simple way to rewrite the macro.
Avenues that I considered:
Expand the macro by hand everywhere: It would work, but the code duplication could make things interesting in the long run.
Write a method that returns an array: This would also work, but it would repeatedly result into code like this:
long tmp[] = bitops(k, l, m, x, y, z);
k = tmp[0];
l = tmp[1];
m = tmp[2];
x = tmp[3];
y = tmp[4];
z = tmp[5];
Write a method that takes an array as an argument: This would mean that all variable names would be reduced to array element references - it would be rather hard to keep track of which index corresponds to which variable.
Create a separate class e.g. State with public fields of the appropriate type and use that as an argument to a method: This is my current solution. It allows the method to alter the variables, while still keeping their names. It has the disadvantage, however, that the State class will get more and more complex, as more macros and variables are added, in order to avoid copying values back and forth among different State objects.
How would you rewrite such a C macro in Java? Is there a more appropriate way to deal with this, using the facilities provided by the standard Java 6 Development Kit (i.e. without 3rd party libraries or a separate preprocessor)?
Option 3, create you own MutableInteger wrapper class.
struct MutableInteger{
public MutableInteger(int v) { this.value = value;}
public int value;
}
public void swap3( MutableInteger k, MutableInteger l, MutableInteger m) {
int t = m.value;
m.value = l.value
l.value=k.value;
k.value=t;
}
Create a separate class e.g. State
with public fields of the appropriate
type and use that as an argument to a
method
This, but as an intermediate step. Then continue refactoring - ideally class State should have private fields. Replace the macros with methods to update this state. Then replace all the rest of your code with methods that update the state, until eventually your program looks like:
System.out.println(State(System.in).hexDigest());
Finally, rename State to SHA1 or whatever ;-)

Categories

Resources