Troubles overriding java method in jruby - java

I'm having some troubles overriding a java method from a jruby class. Since JRuby exposes java methods with both camel and snake case syntaxes, i've tried both approaches to override the same method, but i'm having strange results:
JAVA
package tabaqui;
class MyJavaClass {
public void myMethod() {
System.out.println("Java method");
}
public void invokeMyMethod() {
myMethod();
}
}
RUBY
class MyRubyClass1 < Java::tabaqui.MyJavaClass
def my_method
puts "Ruby method from MyRubyClass1\n";
end
end
class MyRubyClass2 < Java::tabaqui.MyJavaClass
def myMethod
puts "Ruby method from MyRubyClass2\n";
end
end
a = MyRubyClass1.new
a.my_method #output: "Ruby method from MyRubyClass1"
a.invoke_my_method #output: "Java method"
b = MyRubyClass2.new
b.my_method #output: "Java method"
b.invoke_my_method #output: "Ruby method from MyRubyClass2"
The only solution i've found to obtain the expected result (ruby methods invoked in every case) is giving the overridden method an alias after defining it in ruby:
alias_method :myMethod, :my_method
Am i doing something wrong?

while confusing at first sight, this is "expected" once you understand alias ...
MyJavaClass#myMethod will have a my_method alias setup by the JRuby runtime.
in MyRubyClass1 you redefined my_method (alias) thus seeing the expected output.
however you did not override myMethod -> the convention does not work backwards.
while in MyRubyClass2 you redefined myMethod so it ends up doing virtual Java dispatch from invokeMyMethod(), es expected.
while this might seem confusing its how it is, the Java alias conventions are really there for "bare" consumers. while if you're extending a Java class you should stick to proper Java names. there's room for improvement here to re-define Java aliases once a proxy class is generated, although it might be a breaking change.

Related

JavaCPP fails at function disambiguation

I am implementing a Java wrapper for a C++ project using JavaCPP. I have defined mappings for all custom types, but I'm struggling with a call to the std::sort_heap() function that takes a function as an argument.
This is the function call in the C++ code:
std::sort_heap(heap.begin(), heap.end(), comparePairs);
comparePairs is declared like this in this file:
bool comparePairs(
const std::pair<real, int32_t>& l,
const std::pair<real, int32_t>& r) {
return l.first > r.first;
}
When I try to run this with JavaCPP (using the JavaCPP Maven plugin), I get this error:
error: no matching function for call to ‘pop_heap(std::vector<std::pair<float, int> >::iterator, std::vector<std::pair<float, int> >::iterator, <unresolved overloaded function type>)’
std::pop_heap(heap.begin(), heap.end(), comparePairs);
^
Update: the problem seems to be due to the fact that another compairePairs() with a slightly different signature function is declared in another file. The C++ compiler disambiguates them fine, considering that each compairePairs() function is called only within the same file. However, JavaCPP seems to fail at that disambiguation somehow.
This is how the other type mappings are declared:
import org.bytedeco.javacpp.tools.Info;
import org.bytedeco.javacpp.tools.InfoMap;
import org.bytedeco.javacpp.tools.InfoMapper;
[...]
#Properties(value = #Platform(include = {[...]}), target = "[...]")
public class Wrapper implements InfoMapper {
public void map(InfoMap infoMap) {
infoMap.put(new Info("std::vector<std::string>").pointerTypes("StringVector").define())
// more put calls here
;
}
}
Question is thus: why does JavaCPP fail to disambiguate overloaded functions, and how can I fix it?
Note: the C++ code is a third party project, so changing the C++ code is not an option.
Update: the issues appears to be due to the compairPairs() function being declared twice in the C++ code (in two different files), with different signatures.
As described in the comment, wrapping the function call to comparePairs() into a lambda function resolves the issue.
See https://github.com/facebookresearch/fastText/pull/936/commits/cda295f1b5851df0a26a6ac2ab04230fb864a89d

Identifier expected error when calling a method in java

I have this rather simple code written in java. This is actually from a DAQ framework, called Kmax
import kmax.ext.*;
public class Runtime implements KmaxRuntime {
KmaxToolsheet tlsh; // Store a reference to the toolsheet environment
KmaxHist hist1D;
KmaxWidget checkBoxWidget;
public void init(KmaxToolsheet toolsheet) {
tlsh = toolsheet; // Save this reference for use in the toolsheet
hist1D = tlsh.getKmaxHist("HIST1D");
checkBoxWidget = tlsh.getKmaxWidget("CHECK_BOX_CALIB_METH");
tlsh.getKmaxWidget("CHECK_BOX_CALIB_METH").setProperty("VALUE", "1");
}
public void CalibInit(KmaxWidget widget, KmaxHist histo){
histo.setUseXAxisCalibration(stringToBool(widget.getProperty("VALUE")));
histo.update();
}
CalibInit(checkboxWidget,hist1D);
public void GO(KmaxToolsheet toolsheet){}
public void SRQ(KmaxDevice device) {}
public void HALT(KmaxToolsheet toolsheet) {}
} // End of the Runtime object
Note that there I have created an object named CHECK_BOX_CALIB_METH. When I compile this code I get those errors messages
compiler msg>error: invalid method declaration; return type required
compiler msg> CalibInit(checkboxWidget,hist1D);
compiler msg> ^
compiler msg>error: <identifier> expected
compiler msg>CalibInit(checkboxWidget,hist1D);
compiler msg> ^
compiler msg>error: <identifier> expected
compiler msg>CalibInit(checkboxWidget,hist1D);
compiler msg> ^
Note that if I remove the CalibInit method and replace it with
public void CHECK_BOX_CALIB_METH(KmaxWidget widget) {
hist1D.setUseXAxisCalibration(stringToBool(widget.getProperty("VALUE")));
hist1D.update();
}
I get no compile error. The keypoint is that the method's name is the same as the object's name. The reason I created CalibInit() is to avoid having each method for every object of the same type, with the same functionality. Is there a way around it?
How to avoid those errors?
Only variables can declare out side of methods. You can call methods only in methods and constructor (avoiding static context here).
CalibInit(checkboxWidget,hist1D);
Please move that line to any method or constructor , if needed. More specifically call where you need it.
In short: CalibInit(checkboxWidget,hist1D); is orphan now. make it belong to something.
The code
CalibInit(checkboxWidget,hist1D);
that is on a line of its own is not inside any of your methods. The compiler assumes that this is a new method declaration which is probably not what you want.
Side note:
It is not recommended to have methods starting with a upper case character: "Methods should be verbs, in mixed case with the first letter lowercase, with the first letter of each internal word capitalized." from Code Conventions for the Java Programming Language
You can't call
CalibInit(checkboxWidget,hist1D);
directly in the class like you're doing. This instruction should be inside a constructor if your goal is to call it when an instance of Runtime is constructed.
BTW: methods start with a lowercase letter by convention in Java, and you shouldn't call your class Runtime: it will confuse people because a standard Runtime class already existsin the standard libraries.
You are calling CalibInit(checkboxWidget,hist1D) method directly in the class not in any method. Java doesn't support this.

explicitly override a Java method in Jruby?

Is there an explicit way to override a Java method in JRuby-subclass?
public class Yours {
public String hi() {
return "Hello original";
}
}
In a Java I'd use #override to make subclassing explicit.
public class Mine extends Yours {
#Override // throws an error if the above is not a superclass method
public String hi() {
return "Hello override!";
}
}
When I override this in Jruby, I'd like something like this:
class JRMine < Yours
java_overrides # I wish this was there, making sure "wiring" is ok
def hi()
"Hello Jruby"
end
end
Now, is there any equivalent technique to achieve safe overriding?
It seems it could avoid some hard-to-track errors in java integration, due to just relying on method naming.
(Actually I find it would be handy in Ruby generally too, to a lesser extent..)
UPDATE: now packed into gem 'overrides' https://github.com/kares/overrides
with a bit of meta-programming this is possible to do with Ruby methods (and works with JRuby since Java inherited methods show up as Ruby ones) ... I've put it up in a gist :
https://gist.github.com/kares/7434811 ... now that someone finds it useful might put it in a gem :)
usage sample (NOTE: you do not need to hook it up for all classes/modules) JRuby style :
Object.extend Override
class JList < java.util.ArrayList
override
def trim_to_size; super; end
def isEmpty; false; end
override :isEmpty
end

How do I implement a Java interface in Clojure

How do I create a Clojure object that implements this interface and then gets called from Java code?
public interface Doer {
public String doSomethin(String input);
}
Doer clojureDoer = ?;
String output = clojureDoer.doSomethin(input);
reify is strongly preferred for implementing interfaces - proxy is heavy-duty, old, and slow, so should be avoided when possible. An implementation would look like:
(reify Doer
(doSomethin [this input]
(...whatever...)))
As of Clojure 1.6, the preferred approach would be as follows. Assuming you have, on your classpath, the Clojure 1.6 jar and the following clojure file (or its compiled equivalent):
(ns my.clojure.namespace
(:import [my.java.package Doer]))
(defn reify-doer
"Some docstring about what this specific implementation of Doer
does differently than the other ones. For example, this one does
not actually do anything but print the given string to stdout."
[]
(reify
Doer
(doSomethin [this in] (println in))))
then, from Java, you could access it as follows:
package my.other.java.package.or.maybe.the.same.one;
import my.java.package.Doer;
import clojure.lang.IFn;
import clojure.java.api.Clojure;
public class ClojureDoerUser {
// First, we need to instruct the JVM to compile/load our
// Clojure namespace. This should, obviously, only be done once.
static {
IFn require = Clojure.var("clojure.core", "require");
require.invoke(Clojure.read("my.clojure.namespace"));
// Clojure.var() does a somewhat expensive lookup; if we had more than
// one Clojure namespace to load, so as a general rule its result should
// always be saved into a variable.
// The call to Clojure.read is necessary because require expects a Clojure
// Symbol, for which there is no more direct official Clojure API.
}
// We can now lookup the function we want from our Clojure namespace.
private static IFn doerFactory = Clojure.var("my.clojure.namespace", "reify-doer");
// Optionally, we can wrap the doerFactory IFn into a Java wrapper,
// to isolate the rest of the code from our Clojure dependency.
// And from the need to typecast, as IFn.invoke() returns Object.
public static Doer createDoer() {
return (Doer) doerFactory.invoke();
}
public static void main(String[] args) {
Doer doer = (Doer) doerFactory.invoke();
doer.doSomethin("hello, world");
}
}
With proxy
See the proxy macro. Clojure Docs have some examples. It's also covered on Java Interop page.
(proxy [Doer] []
(doSomethin [input]
(str input " went through proxy")))
proxy returns an object implementing Doer. Now, to access it in Java you have to use gen-class to make your Clojure code callable from Java. It's covered in an answer to the "Calling clojure from java" question.
With gen-class
(ns doer-clj
(:gen-class
:name DoerClj
:implements [Doer]
:methods [[doSomethin [String] String]]))
(defn -doSomethin
[_ input]
(str input " went through Clojure"))
Now save it as doer_clj.clj, mkdir classes and compile it by calling in your REPL (require 'doer-clj) (compile 'doer-clj). You should find DoerClj.class ready to be used from Java in classes directory
For a more general take on this question, this diagram can be freaking useful when you are in need for some kind of Java-interop:
https://github.com/cemerick/clojure-type-selection-flowchart
If doSomethin() is defined in your interface, you should not mention it in :methods. Quote from http://clojuredocs.org/clojure_core/clojure.core/gen-class:
:methods [ [name [param-types] return-type], ...]
The generated class automatically defines all of the non-private
methods of its superclasses/interfaces. This parameter can be used
to specify the signatures of additional methods of the generated
class. Static methods can be specified with ^{:static true} in the
signature's metadata. Do not repeat superclass/interface signatures
here.

Java or any other language: Which method/class invoked mine?

I would like to write a code internal to my method that print which method/class has invoked it.
(My assumption is that I can't change anything but my method..)
How about other programming languages?
EDIT: Thanks guys, how about JavaScript? python? C++?
This is specific to Java.
You can use Thread.currentThread().getStackTrace(). This will return an array of StackTraceElements.
The 2nd element in the array will be the calling method.
Example:
public void methodThatPrintsCaller() {
StackTraceElement elem = Thread.currentThread.getStackTrace()[2];
System.out.println(elem);
// rest of you code
}
If all you want to do is print out the stack trace and go hunting for the class, use
Thread.dumpStack();
See the API doc.
Justin has the general case down; I wanted to mention two special cases demonstrated by this snippit:
import java.util.Comparator;
public class WhoCalledMe {
public static void main(String[] args) {
((Comparator)(new SomeReifiedGeneric())).compare(null, null);
new WhoCalledMe().new SomeInnerClass().someInnerMethod();
}
public static StackTraceElement getCaller() {
//since it's a library function we use 3 instead of 2 to ignore ourself
return Thread.currentThread().getStackTrace()[3];
}
private void somePrivateMethod() {
System.out.println("somePrivateMethod() called by: " + WhoCalledMe.getCaller());
}
private class SomeInnerClass {
public void someInnerMethod() {
somePrivateMethod();
}
}
}
class SomeReifiedGeneric implements Comparator<SomeReifiedGeneric> {
public int compare(SomeReifiedGeneric o1, SomeReifiedGeneric o2) {
System.out.println("SomeRefiedGeneric.compare() called by: " + WhoCalledMe.getCaller());
return 0;
}
}
This prints:
SomeRefiedGeneric.compare() called by: SomeReifiedGeneric.compare(WhoCalledMe.java:1)
somePrivateMethod() called by: WhoCalledMe.access$0(WhoCalledMe.java:14)
Even though the first is called "directly" from main() and the second from SomeInnerClass.someInnerMethod(). These are two cases where there is a transparent call made in between the two methods.
In the first case, this is because we are calling the bridge method to a generic method, added by the compiler to ensure SomeReifiedGeneric can be used as a raw type.
In the second case, it is because we are calling a private member of WhoCalledMe from an inner class. To accomplish this, the compiler adds a synthetic method as a go-between to override the visibility problems.
the sequence of method calls is located in stack. this is how you get the stack: Get current stack trace in Java then get previous item.
Since you asked about other languages, Tcl gives you a command (info level) that lets you examine the call stack. For example, [info level -1] returns the caller of the current procedure, as well as the arguments used to call the current procedure.
In Python you use the inspect module.
Getting the function's name and file name is easy, as you see in the example below.
Getting the function itself is more work. I think you could use the __import__ function to import the caller's module. However you must somehow convert the filename to a valid module name.
import inspect
def find_caller():
caller_frame = inspect.currentframe().f_back
print "Called by function:", caller_frame.f_code.co_name
print "In file :", caller_frame.f_code.co_filename
#Alternative, probably more portable way
#print inspect.getframeinfo(caller_frame)
def foo():
find_caller()
foo()
Yes, it is possible.
Have a look at Thread.getStackTrace()
In Python, you should use the traceback or inspect modules. These will modules will shield you from the implementation details of the interpreter, which can differ even today (e.g. IronPython, Jython) and may change even more in the future. The way these modules do it under the standard Python interpreter today, however, is with sys._getframe(). In particular, sys._getframe(1).f_code.co_name provides the information you want.

Categories