Is there a way to create a Lua function in Java and pass it to Lua to assign it into a variable?
For example:
In my Java class:
private class doSomething extends ZeroArgFunction {
#Override
public LuaValue call() {
return "function myFunction() print ('Hello from the other side!'); end" //it is just an example
}
}
In my Lua script:
myVar = myHandler.doSomething();
myVar();
In this case, the output would be: "Hello from the other side!"
Try using Globals.load() to construct a function from a script String, and use LuaValue.set() to set values in your Globals:
static Globals globals = JsePlatform.standardGlobals();
public static class DoSomething extends ZeroArgFunction {
#Override
public LuaValue call() {
// Return a function compiled from an in-line script
return globals.load("print 'hello from the other side!'");
}
}
public static void main(String[] args) throws Exception {
// Load the DoSomething function into the globals
globals.set("myHandler", new LuaTable());
globals.get("myHandler").set("doSomething", new DoSomething());
// Run the function
String script =
"myVar = myHandler.doSomething();"+
"myVar()";
LuaValue chunk = globals.load(script);
chunk.call();
}
Related
I am trying to migrate the python library into the java native script but I facing extreme complexity with the parameters while migration.
Here the code I need to migrate the python method with the default & optional parameters with different datatypes into the java method:
def connect_network(self,
bssid=None,
proto="http",
check_redirect_code=True,
redirect_code='302',
portal_url=None,
subscriber_portal='scg',
expect_href_list_zd_sp='google',
check_user_block=False,
redirect_url='',
tnc_content="",
path="/tmp/"):
pass
Here is my example code which I tried in java equivalent:
public class LinuxClientUtils {
public void DefaultNameParameter1(HashMap<Integer, String> params){
System.out.Println(params.toString());
}
public void DefaultNameParameter2(Map.Entry<String, String>... params){
System.out.Println(params.toString());
}
public void DefaultNameParameter3(Optional<String> name, Optional<String> age){
System.out.Println(name.toString());
}
}
I will import that Java library in the robot framework and call the method like this,
*** Settings ***
Library test.LinuxClientUtils
*** Test Cases ***
Testing
[tags] service
[Documentation] Add Network
Default Name Parameter3 req_network_id=89
Still, None of the methods didn't work.
I have tried few Methods from the following URLs Link-1
Link-2 But I am unable to figure it out from those links.
I'm new to JAVA programming and haven't been able to fix this one. Any help would be great, thanks.
Create a new class for a parameter object. It will have each of the parameters as a field.
The constructor of this parameter class has no parameters. Instead, each field has a default value. (null and false are automatically assigned by default for object and boolean fields, anyway.)
Your function will just take a parameter object as a single parameter.
public class A {
static class ParameterObject {
public ParameterObject(){
//empty
}
private int x;
private boolean b;
private String s;
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public boolean isB() {
return b;
}
public void setB(boolean b) {
this.b = b;
}
public String getS() {
return s;
}
public void setS(String s) {
this.s = s;
}
}
public static void f(ParameterObject o){
//Do something with object
}
public static void main(String[] args) {
ParameterObject paramObj=new ParameterObject();
paramObj.setX(10);
f(paramObj);
}
}
I need to configure some attribute in ScriptEngine- or ScriptContext-level, to be used in Java methods.
So, how to get a reference to that ScriptContext in order to retrieve the value?
Example: setting the attribute:
public static void main(String[] args) throws Exception {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.getContext().setAttribute("param1", "paramValue", ScriptContext.ENGINE_SCOPE);
engine.put("MyWindow", engine.eval("Java.type(\"" + MyWindow.class.getName() + "\")"));
engine.eval("print(new MyWindow().test());");
}
MyWindow implementation: how to get that attribute?
public class MyWindow {
public String test() {
// how to get 'param1' value here
return "in test";
}
}
Pass it in:
engine.eval("print(new MyWindow().test(param1));");
// ^^^^^^
// vvvvvvvvvvvvv
public String test(String param1) {
// how to get 'param1' value here
return "in test";
}
Update
If you have code with a call stack like javaMethod1 -> JavaScript -> javaMethod2, and you want a value from javaMethod1 to be available to javaMethod2, without changing the JavaScript to pass it on, use a ThreadLocal.
Since your code is in main you could just use a static directly, but I'm assuming your context is more complex. The code below works even in multi-threaded contexts. The ThreadLocal can be stored anywhere, it just has to be static and available to both java methods.
public static void main(String[] args) throws Exception {
MyWindow.param1.set("paramValue");
try {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.eval("var MyWindow = Java.type(\"" + MyWindow.class.getName() + "\");" +
"print(new MyWindow().test());");
} finally {
MyWindow.param1.remove();
}
}
public class MyWindow {
public static final ThreadLocal<String> param1 = new ThreadLocal<>();
public String test() {
String value = param1.get();
return "in test: param1 = " + value;
}
}
I have made a trival example from luaj website.. LuaJ
I am trying to run a function on the current object which is currently being used. but luaJ is making a new object.
How can I run the function on the current object, not making a new one.
cosidering the following code...
import org.luaj.vm2.Globals;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.TwoArgFunction;
import org.luaj.vm2.lib.ZeroArgFunction;
import org.luaj.vm2.lib.jse.JsePlatform;
public class luaTest extends TwoArgFunction {
public luaTest() {}
changeInt mytest=new changeInt();
public LuaValue call(LuaValue modname, LuaValue env) {
LuaValue library = tableOf();
library.set( "countup", new countup(mytest) );
env.set( "luaTest", library );
return library;
}
void run() {
Globals globals = JsePlatform.standardGlobals();
mytest.setA(10); // Setting it 10 before calling the script
LuaValue chunk = globals.loadfile("script.lua");
chunk.call();
}
class countup extends ZeroArgFunction {
changeInt mytest;
public countup(changeInt a)
{
mytest=a;
}
public LuaValue call() {
return LuaValue.valueOf(mytest.countup());
}
}
}
the changeInt class is simple one variable...
public class changeInt {
int a = 1;
public int countup(){
return a++;
}
public void setA(int x)
{
a=x;
}
}
luaScript is simple..
require 'luaTest'
print('count',luaTest.countup())
print('count',luaTest.countup())
print('count',luaTest.countup())
is there any way around it..
Yeah it was very trival for java programmers (I am very new to java)..
I used Singleton pattern and it solved the problem.
I have the following code in C++ (Cocos2d) :
typedef void (CCObject::*SEL_CallFunc)();
CCCallFunc * CCCallFunc::actionWithTarget(CCObject* pSelectorTarget,
SEL_CallFunc selector) {
CCCallFunc *pRet = new CCCallFunc();
if (pRet && pRet->initWithTarget(pSelectorTarget)) {
pRet->m_pCallFunc = selector;
pRet->autorelease();
return pRet;
}
CC_SAFE_DELETE(pRet);
return NULL;
}
When converting with swig to java I get the following :
public static CCCallFunc actionWithTarget(CCObject pSelectorTarget, SWIGTYPE_m_CCObject__f___void selector) {
long cPtr = cocos2dxMappingJNI.CCCallFunc_actionWithTarget(CCObject.getCPtr(pSelectorTarget), pSelectorTarget,
SWIGTYPE_m_CCObject__f___void.getCMemberPtr(selector));
return (cPtr == 0) ? null : new CCCallFunc(cPtr, false);
}
Where SWIGTYPE_m_CCObject__f___void is just a pointer I can't use.
How do I implement this in the SWIG interface ?
I've looked into this solution stackoverflow but couldn't implement it for my case.
I don't believe SWIG supports member function pointers in any meaningful way. However, it's possible to get it done with JavaCPP. Given this C++ code in a file named MemberFunction.h:
class MyClass {
public:
virtual ~MyClass() { }
};
typedef void (MyClass::*MyFunction)(const char *str);
void callback(MyClass* cls, MyFunction fct, const char *str) {
(cls->*fct)(str);
}
We can define and use the callback this way in Java:
import org.bytedeco.javacpp.*;
import org.bytedeco.javacpp.annotation.*;
#Platform(include="MemberFunction.h")
public class MemberFunction {
static { Loader.load(); }
public static abstract class MyClass extends Pointer {
public MyClass() { allocate(); }
private native void allocate();
#Virtual public abstract void myCallback(String str);
#Virtual #MemberGetter #Name("myCallback")
public static native MyFunction getMyCallback();
}
#Namespace("MyClass")
public static class MyFunction extends FunctionPointer {
public native void call(MyClass cls, String str);
}
public static native void callback(MyClass cls, MyFunction fct, String str);
public static void main(String[] args) {
MyClass cls = new MyClass() {
public void myCallback(String str) {
System.out.println(str);
}
};
MyFunction fct = MyClass.getMyCallback();
callback(cls, fct, "Hello World");
}
}
Which builds fine and outputs the expected result:
$ javac -cp javacpp.jar MemberFunction.java
$ java -jar javacpp.jar MemberFunction
$ java -cp javacpp.jar MemberFunction
Hello World
You probably want to look at a typemap for "SEL_CallFunc selector". The typemap squirrels the original language callback, which is called via a tramploline function. There are python examples here and here. You'll find various similar questions for java on SO.
i'm totally new to java. i 'm try to create my first program & i get this error.
E:\java>javac Robot.java
Robot.java:16: error: illegal start of expression
public String CreateNew (); {
^
Robot.java:16: error: ';' expected
public String CreateNew (); {
^
2 errors
below is my program.
public class Robot {
public static void main(String args[]){
String model;
/*int year;*/
String status;
public String CreateNew () {
Robot optimus;
optimus = new Robot();
optimus.model="Autobot";
/*optimus.year="2008";*/
optimus.status="active";
return (optimus.model);
}
}
}
You're trying to define a method (CreateNew) within a method (main), which you cannot do in Java. Move it out of the main; and as model and status appear to be instance variables (not method variables), move them as well:
public class Robot {
// Member variables
String model;
/*int year;*/
String status;
// main method
public static void main(String args[]){
// Presumably more stuff here
}
// Further method
public String CreateNew () {
Robot optimus;
optimus = new Robot();
optimus.model="Autobot";
/*optimus.year="2008";*/
optimus.status="active";
return (optimus.model);
}
}
Based on its content, you may want CreateNew to be static (so it can be called via Robot.CreateNew rather than via a Robot instance). Like this:
public class Robot {
// Member variables
String model;
/*int year;*/
String status;
// main method
public static void main(String args[]){
// Presumably more stuff here
}
// Further method
public static String CreateNew () {
// ^----------------------------- here's the change
Robot optimus;
optimus = new Robot();
optimus.model="Autobot";
/*optimus.year="2008";*/
optimus.status="active";
return (optimus.model);
}
}
Used as
String theModel = Robot.CreateNew();
...although it's unclear to me why you want to create a Robot instance and then throw it away and just return the model instance member's value.
Somewhat off-topic, but the overwhelming convention in Java is that method names (static or instance) start with a lower-case letter, e.g. createNew rather than CreateNew.
You didn't close your main method before you create the CreateNew() one. In fact I don't think you meant to have a main method in your Robot class, you should have only one main method for your whole program. And your CreateNew should be a constructor:
public class Robot {
String model;
/*int year;*/
String status;
public Robot () {
this.model="Autobot";
this.status="active";
}
}
}
and then in another class that contains your main method (or it could be in the same class too):
public class OtherClass {
public static void main(String[] args) {
Robot optimus = new Robot(); // here you create an instance of your robot.
}
}
then you can have a second constructor that takes in parameter the model and status like that:
public Robot (String m, Status s) {
this.model=m;
this.status=s;
}
and finally in your main:
Robot prime = new Robot("aName", "aStatus");