Dlouho jsem hledal, jak uzivatelum snadno umoznit psat pluginy do me aplikace. Hodne se pouziva VBA (Visual Basic for Applications), Lisp a Lua. Me je nejblizsi JavaScript, navic v nem hodne lidi umi.
Moje potreba byla jednoducha: predat JavaScriptu promenne z Pythonu/Javy, pomoci JS s nima neco udelat a pote vratit vysledek.
Takze napriklad predam pole namerenych teplot za posledni hodinu. Uzivateluv algoritmus je vyhodnoti a vrati, jestli zapnout/vypnout kotel.
Java ma podporu vybornou, zvlaste od Javy 8. V Pythonu je to horsi, ale take funkcni.
Python
Zde je funkcni ukazka:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# https://blog.sqreen.io/embedding-javascript-into-python/ # http://stackoverflow.com/a/366763/1974494 # http://stackoverflow.com/a/601168/1974494 import signal from contextlib import contextmanager from py_mini_racer import py_mini_racer ctx = py_mini_racer.MiniRacer() # --------------------- print( ctx.eval('1+1') ) # --------------------- my_script_1 = """ function maxNumber(arr) { var largest = arr[0]; for (var i = 0; i < arr.length; i++) { if (largest < arr[i] ) { largest = arr[i]; } } return largest; } """ ctx.eval(my_script_1) arr = [3, 6, 2, 56, 32, 5, 89, 32] max = ctx.call("maxNumber", arr) print(max) # --------------------- my_script_2 = """ function sleep(delay) { var start = new Date().getTime(); while (new Date().getTime() < start + (delay * 1000)); return ":-)"; } """ ctx.eval(my_script_2) class TimeoutException(Exception): pass @contextmanager def time_limit(seconds): def signal_handler(signum, frame): raise TimeoutException("Timed out!") signal.signal(signal.SIGALRM, signal_handler) signal.alarm(seconds) try: yield finally: signal.alarm(0) try: with time_limit(5): result = ctx.call("sleep", 3) print(result) except TimeoutException as msg: print("Timed out!") try: with time_limit(5): result = ctx.call("sleep", 7) print(result) except TimeoutException as msg: print("Timed out!") # --------------------- |
Prvni JavaScript najde v Python poli cisel nejvesti a vrati ho.
Druhy priklad je na pluginy vhodnejsi, nastavi timeout pro JavaScriptovy kod. Pokud uzivatel svuj algoritmus napr. zacykli, ukonci ho.
Zdrojak je na pochopeni dostatecny. A tady je jeho vystup:
1 2 3 4 5 6 7 |
/usr/bin/python3.5 /home/martin/PycharmProjects/JavaScript/miniracer_test1.py 2 89 :-) Timed out! Process finished with exit code 0 |
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
package test.test; public class User { private String name; public User() { } public String getName() { return name; } public void setName(String name) { this.name = name; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 |
package test.test; import javax.script.Bindings; import javax.script.Compilable; // Require Java 8 !!! import javax.script.CompiledScript; // Require Java 8 !!! import javax.script.Invocable; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; import javax.script.SimpleBindings; public class JavaScriptInJava { public static void main(String[] args) throws ScriptException, NoSuchMethodException { ScriptEngineManager manager = new ScriptEngineManager(); ScriptEngine engine = manager.getEngineByName("JavaScript"); /* ----------------------------------------------------------------------- */ // Put (string) param to JavaScript. engine.put("testString", "Hello, world!"); engine.eval("print(testString)"); // Put (string) param to JavaScript. /* ----------------------------------------------------------------------- */ // Find max number in int array with JavaScript: int[] array = { 3, 6, 2, 56, 32, 5, 89, 32 }; engine.put("arr", array); String script = "var largest = arr[0]; " + "function maxNumber(arr) { " + " for (var i = 0; i < arr.length; i++) { " + " if (largest < arr[i] ) { " + " largest = arr[i]; " + " } " + " } " + " return largest; " + "} " + "maxNumber(arr); "; Number result = (Number) engine.eval(script); System.out.println("Max=" + result.longValue()); // Find max number in int array with JavaScript. /* ----------------------------------------------------------------------- */ // Work with Java class from JavaScript: String userScript = "user1.setName(\"Test User\"); " + "print( user1.getName() ); "; Bindings bindings = new SimpleBindings(); User u = new User(); bindings.put("user1", u); engine.eval(userScript, bindings); // Require Java 8 !!! // Compile JavaScript (faster): if (engine instanceof Compilable) { System.out.println(" Compiling..."); Compilable compEngine = (Compilable) engine; CompiledScript cs = compEngine.compile(userScript); cs.eval(bindings); } else { engine.eval(userScript, bindings); } // Compile JavaScript (faster). // Require Java 8 !!! // Work with Java class from JavaScript. /* ----------------------------------------------------------------------- */ // Use JavaScript function in Java code: String math = "function addition(a, b) { " + " return a+b; " + "} " + " " + "function substraction(a, b) { " + " return a-b; " + "} " + " "; engine.eval(math); Invocable inv = (Invocable) engine; int a = 10; int b = 5; System.out.println("A=" + a + " B=" + b); Object aPlusB = inv.invokeFunction("addition", a, b); System.out.println("A+B = " + aPlusB); Object[] inputParams = { new Integer(10), b }; Object aMinusB = inv.invokeFunction("substraction", inputParams); System.out.println("A-B = " + aMinusB); int x = (Integer) aPlusB + 1; System.out.println("aPlusB + 1 = " + x); // Use JavaScript function in Java code. /* ----------------------------------------------------------------------- */ } } |
Na ukazce je videt opet nalezeni nejvetsiho cisla. Mnohem zajimavejsi vsak je pristup k Java objektum z JavaScriptu – trida User.
Od Javy 8 je mozne JavaScript zkompilovat a tim ohromne urychlit jeho provadeni.
Jde pouze o ukazku, ze to jde 🙂