Saturday, February 21, 2015

Subclass from Java


You can subclass from a Java class in Rusthon using the C++11 backend. JNI wrappers are generated using Giws and automatically compiled with the final exe by putting the Giws XML inside your markdown project.

Giws only supports regular and class methods, and basic types. Constructors and properties of Java classes are not exposed, and require extra wrapping by hand. Hopefully this will get fixed soon, github issues: constructors, properties

source code: https://github.com/rusthon/Rusthon/blob/master/examples/giws_subclass.md

java

package mymod;

public class A{
 public A(){}
 public void foo(){
  System.out.println("A.foo from java.");
 }
}

public class B extends A{
 public int y;
 public B(){ this.y=420; }
 public void bar(int i){
  System.out.println("B.bar from java.");
  this.y = i;
 }
}

rusthon

The example below shows how the property y (defined in the Java class) is exposed to Rusthon with inlined C++ that directly uses JNI calls. This is not actually the best way to do this, it would be better to write getter/setter functions in Java, and wrap those normally with Giws XML. This way of going direct with inlined JNI is only useful if you were loading a JAR and did not have access to the original Java source code to add the getter/setters.

import jvm
jvm.namespace('mymod')

@jvm
class C(B):
 def __init__(self, x:int):
  self.x = x

 def get_y(self) ->int:
  inline('''
  auto env = getCurrentEnv();
  auto fid = env->GetFieldID(this->instanceClass, "y", "I");
  return env->GetIntField(this->instance, fid);
  ''')

 def hey(self):
  print('hey from rusthon')

c++ output of C

using namespace mymod;
class C:  public B {
  public:
 std::string __class__;
 int  x;
 C* __init__(int x);
 int get_y();
 void hey();
 C(JavaVM* _jvm) : B(_jvm) {__class__ = std::string("C");}
 std::string getclassname() {return this->__class__;}
};
 int C::get_y() {
  auto env = getCurrentEnv();
  auto fid = env->GetFieldID(this->instanceClass, "y", "I");
  return env->GetIntField(this->instance, fid);
 }
 void C::hey() {
  std::cout << std::string("hey from rusthon") << std::endl;
 }

 C* C::__init__(int x) {
  this->x = x;
  return this;
 }

When creating an instance of C you still need to wrap it with the special jvm call so that the Java proxy object is also created.

def main():
 c = jvm( C(999) )
 print c.x  ## x can be used directly, prints 999
 print c.get_y()  ## prints 420
 c.foo()
 c.bar( 100 )     ## sets y to 100
 print c.get_y()  ## prints 100
 c.hey()

No comments:

Post a Comment