weikipeng / javacpp

Automatically exported from code.google.com/p/javacpp
GNU General Public License v2.0
0 stars 0 forks source link

Pass Java fields as a struct on stack, without native heap allocation #28

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
This is a suggestion not a request because this is already possible with 
@MemberGetter/Setter way.

My thought is in java, use public member field like c. For example,

Say MyObj.h is like below,

class Option {
  public:
  int write_buffer_size;
  bool create_if_missing;
}
class MyObj {
  public:
  void put(Option& options, std::string& data);
}

Then if I make MyObj.java like below,

class Option extends Pointer {
  @NativeField  // this indicates to sync before/after used.
  public int write_buffer_size;
  @NativeField  // this indicates to sync before/after used.
  public bool create_if_missing;
}
class MyObj extends Pointer {
  native void put(@ByRef Option& options, ...);
}

jniMyObj.cpp would be like below,

JNIEXPORT jobject JNICALL Java_packageName_MyObj_Put(JNIEnv* env, jobject obj, 
jobject arg0, ...) {
  MyObj* ptr = (MyObj*)jlong_to_ptr(env->GetLongField(obj, JavaCPP_addressFID));
  Option* ptr0 = (Option*)jlong_to_ptr(env->GetLongField(arg0, JavaCPP_addressFID));

  // step 1 : copy from java to c before used
  ptr0->write_buffer_size = env->GetIntFIeld(arg0, Option_write_buffer_sizeFID);
  ptr0->create_if_missing = env->GetBooleanFIeld(arg0, Option_create_if_missingFID);
  ...

  ptr->Put(ptr0, ...);

  // step 2 : copy from c to java after used
  env->SetIntFIeld(arg0, Option_write_buffer_sizeFID, ptr0->write_buffer_size);
  env->SetBooleanFIeld(arg0, Option_create_if_missingFID, ptr0->create_if_missing);
}

If Option is read-only(@Const) then step 2 is unnecessary.
If Option is write-only(?) then step 1 is unnecessary.

This is what I think. There maybe many issues I haven't thought about.
But basically this is my suggestion.
It would make javacpp much more powerful.

Original issue reported on code.google.com by noranb...@gmail.com on 1 Nov 2012 at 12:52

GoogleCodeExporter commented 9 years ago
That's basically what JNA does, so you could use that if you wish.

The problem with that approach is that it duplicates all data, which gets out 
of sync if we don't sync them explicitly. There is no foolproof way to sync 
them automatically unfortunately.

BTW, if you are interested in a shorter syntax, you should look into Scala. 
It's possible to shorten statements like 
    public native int data(); public native void data(int data);
to just
    @native var data: Int
if we extend the meaning of the `@native` annotation to variables that is. 
Would that satisfy your needs?

Original comment by samuel.a...@gmail.com on 1 Nov 2012 at 1:45

GoogleCodeExporter commented 9 years ago
I thought about sync issue too.
But maybe it wouldn't be a problem for read-only or write-only?

I didn't know much about JNA, Scalar. (JavaCPP is the first jni tool for
me.:) )
Thank you for info.

Original comment by noranb...@gmail.com on 1 Nov 2012 at 2:00

GoogleCodeExporter commented 9 years ago
It could be interesting if we do not keep a native structure on the heap. That 
is, it gets recreated every time we call a function. We wouldn't even need any 
special annotation then. On function call, JavaCPP would basically create a 
"struct" on the stack, copy all the fields, and that's it. It would work very 
much like the arguments themselves actually.

I think it's a good feature! Good idea. It would require some amount work, so 
I'm not sure that I'll be working on it myself soon though...

Original comment by samuel.a...@gmail.com on 1 Nov 2012 at 2:53

GoogleCodeExporter commented 9 years ago
Yes, that's what I meant.
This will be useful and intuitive for primitive type member field. (Maybe
same can be applied to Pointer type)
Of course overhead for every copy is on user's own.

I like your renamed summary. :)

Original comment by noranb...@gmail.com on 1 Nov 2012 at 3:04