I thought that this would be a simple problem but I have had some difficulty finding an answer.
I have a struct defined in C++, let's say:
struct MyStruct
{
int a;
int b;
};
This gets wrapped into Java proxy class MyStruct by SWIG. I have a function in C++ which takes an array of struct MyStructs:
void myFunction(struct MyStruct arg[], int amount);
SWIG sees a pointer parameter and therefore generates the Java wrapper of the function to use a single MyStruct object as its parameter:
void myFunction(MyStruct arg, int amount) { /**/ }
How do I get SWIG to generate the Java function to take an array of MyStruct Java objects? I have been able to figure it out for arrays of primitive types but have not found a way to get it working for custom wrapped types.
So my desired Java function signature would be this:
void myFunction(MyStruct[] arg, int amount);
Edit: Updated wording to use proper SWIG nomenclature of proxy classes.
I was able to create a working solution using an intermediary array class generated using %array_class from carrays.i along with in and javain typemaps. A complete working example with the solution can be found in my gist.
If anyone can come up with a better solution or improvements then I would be much appreciated. A drawback of my solution is that you would need to create an additional Java array proxy class for each different proxy class that you wanted to use in this way, which could clutter up the Java API. This could be improved slightly by making the array proxy classes package-private using the javaclassmodifiers typemap.
Related
I'm trying to call from C++ into java. I've understood the cux of this answer but I feel I'm not able to achieve the last mile. What classes and methods do I have to use to call Java from C++?
Also not enough points to post comments on there. I basically get that I create the object from java and pass it along in one of my calls into C++. I then get that I could potentially cache it or immedately call into the callback.
This is how my djinni file looks like
my_client_interface = interface +j {
log_string(str: string): bool;
}
get_my_record = interface +c {
static create(): get_my_record;
method_returning_nothing(value: i32);
add_to_string(value: string);
method_returning_something(key: my_record): my_record;
set_callback(cb: my_client_interface);
}
I have no issue creating and passing along the logger callback from java but what concrete class do I call the logger against.
void GetMyRecordImpl::set_callback(const std::shared_ptr<MyClientInterface> & cb)
{
cb->???????
}
since MyClientInterface is still abstract it errors out obviously with
error: member access into incomplete type 'std::__ndk1::shared_ptr<helloworld::MyClientInterface>::element_type' (aka 'helloworld::MyClientInterface')
But if I implement a concrete class against it obviously it's going to call the concrete classes log method and not the one in java. I do see what I need in
bool NativeMyClientInterface::JavaProxy::log_string(const std::string & c_str) {
auto jniEnv = ::djinni::jniGetThreadEnv();
::djinni::JniLocalScope jscope(jniEnv, 10);
const auto& data = ::djinni::JniClass<::djinni_generated::NativeMyClientInterface>::get();
auto jret = jniEnv->CallBooleanMethod(Handle::get().get(), data.method_logString,
::djinni::get(::djinni::String::fromCpp(jniEnv, c_str)));
::djinni::jniExceptionCheck(jniEnv);
return ::djinni::Bool::toCpp(jniEnv, jret);
}
but how would I create the NativeMyClientInterface object needed from the shared_pointer pointing to my abstract class MyClientInterface ?
I wasn't including #include "my_client_interface.hpp" :| the error makes so much sense now.
If you want to use Java object in your C++ code, you got to implement and instantiate that object in Java. Djinni may be perceived as Java Native Interface (JNI) code generator. What you need is Java application, which parts are implemented in C++.
Each interface declared in Djinni is generated for C++ and Java (or Objective-C), so there must be two classes with implementation. One is generated by Djinni and it is a proxy that allows cross-language communication. The other one must be implemented by a programmer.
Regarding your compilation error, I believe you are missing an include directive in the file where GetMyRecordImpl is defined, something like:
#include "generated/MyClientInterface.hpp"
I have a C API that I'm trying to use within Clojure, through the JNA API. My issue can best be demonstrated with the following example. Say I have this C code in a library:
typedef struct {
int foo;
int bar;
double baz;
} MyStruct;
MyStruct createStruct() {
MyStruct myStruct;
myStruct.foo = 3;
myStruct.bar = 4;
myStruct.baz = 3.14;
return myStruct;
}
double addStruct(MyStruct myStruct) {
return myStruct.foo + myStruct.bar + myStruct.baz;
}
In this example, I'd like to call createStruct, and then pass that result to addStruct. The important point here is that MyStruct is passed by value as both a return type and an argument. At no point do I need to actually read the values of the fields in MyStruct.
Additionally, in my system, native functions are wrapped like this:
; `quux` is defined in `some-lib` and returns an `int`
(let [fn- (com.sun.jna.Function/getFunction "some-lib" "quux")]
(fn [& args]
(.invoke fn- Integer (to-array args))))
The goal is to get a type to substitute for Integer above that will wrap MyStruct as a value.
The only resource that I've found covering this subject is this article, but it only discusses how to pass structs by reference.
Given that, here are the different approaches I've tried to take to solve this problem:
Create a class that inherits from Structure, which is JNA's built-in mechanism for creating and using structs. Given the information on that page, I tried to create the following class using only Clojure:
class MyStruct extends Structure implements Structure.ByValue {
int foo;
int bar;
double baz;
}
deftype doesn't work for this scenario, since the class needs to inherit from the abstract class Structure, and gen-class doesn't work because the class needs to have the public non-static fields foo, bar and baz.
From what I can tell, none of the standard Clojure Java interop facilities can create the above class.
Create a class that inherits from Structure and override the struct field getter/setter methods. Since gen-class is (I believe) the only Clojure construct that allows for direct inheritance, and it doesn't support multiple public non-static fields, the next alternative is to simply not use fields at all. Looking at the Structure abstract class documentation, it seems like there's a concoction of overrides possible to use 'virtual' struct fields, such that it really gets and sets data from a different source (such as the state field from gen-class). Looking through the documentation, it seems like overriding readField, writeField, and some other methods may have the intended effect, but the I was unclear how to do this from reading the documentation, and I couldn't find any similar examples online.
Use a different storage class. JNA has a myriad of classes for wrapping native types. I'm wondering if, rather than defining and using a Structure class, I could use another generic class that can take an arbitrary number of bits (like how Integer can hold anything that's 4 bits wide, regardless of what type the source 'actually' is). Is it possible to, for example, say that a function returns an array of bytes of length 16 (since sizeof(MyStruct) is 16)? What about wrapping a fixed-size array in a container class that implements NativeMapped? I couldn't find examples of how to do either.
Clojure actually embeds a forked version of ASM, which is used for generating and loading JVM bytecode.
On top of this library, I built small DSL (that's incomplete and probably broken) that allows for creating arbitrary Java classes, with a Java-like syntax. Currently, it's just a GitHub gist, and only supports extending classes, implementing interfaces, adding constructors that call superclass constructors, and fields.
Here's the solution to the above question, using this DSL:
(def-class MyStruct :extends com.sun.jna.Structure
:implements [com.sun.jna.Structure$ByValue]
; Declare all the constructors, which just forward their
; arguments to the constructors of com.sun.jna.Structure
(com.sun.jna.Structure [])
(com.sun.jna.Structure [com.sun.jna.TypeMapper])
(com.sun.jna.Structure [Integer])
(com.sun.jna.Structure [Integer com.sun.jna.TypeMapper])
(com.sun.jna.Structure [com.sun.jna.Pointer])
(com.sun.jna.Structure [com.sun.jna.Pointer Integer])
(com.sun.jna.Structure [com.sun.jna.Pointer Integer com.sun.jna.TypeMapper])
; Declare the fields of the struct
^Integer foo
^Integer bar
^Double baz)
Now, I can do the following:
(defn createStruct [& args]
(let [fn- (com.sun.jna.Function/getFunction "some-lib" "createStruct")]
(.invoke fn- MyStruct (to-array args))))
(defn addStruct [& args]
(let [fn- (com.sun.jna.Function/getFunction "some-lib" "addStruct")]
(.invoke fn- Double (to-array args))))
(addStruct (createStruct))
; => 10.14
I've got some C functions which I am calling through JNI which take a pointer to a structure, and some other functions which will allocate/free a pointer to the same type of structure so that it is a bit easier to deal with my wrapper. Surprisingly, the JNI documentation says very little about how to deal with C structures.
My C header file looks like so:
typedef struct _MyStruct {
float member;
} MyStruct;
MyStruct* createNewMyStruct();
void processData(int *data, int numObjects, MyStruct *arguments);
The corresponding JNI C wrapper file contains:
JNIEXPORT jobject JNICALL
Java_com_myorg_MyJavaClass_createNewMyStruct(JNIEnv *env, jobject this) {
return createNewMyStruct();
}
JNIEXPORT void JNICALL
Java_com_myorg_MyJavaClass_processData(JNIEnv *env, jobject this, jintArray data,
jint numObjects, jobject arguments) {
int *actualData = (*env)->GetIntArrayElements(env, data, NULL);
processData(actualData, numObjects, arguments);
(*env)->ReleaseIntArrayElements(env, data, actualData, NULL);
}
...and finally, the corresponding Java class:
public class MyJavaClass {
static { System.loadLibrary("MyJniLibrary"); }
private native MyStruct createNewMyStruct();
private native void processData(int[] data, int numObjects, MyStruct arguments);
private class MyStruct {
float member;
}
public void test() {
MyStruct foo = createNewMyStruct();
foo.member = 3.14159f;
int[] testData = new int[10];
processData(testData, 10, foo);
}
}
Unfortunately, this code crashes the JVM right after hitting createNewMyStruct(). I'm a bit new to JNI and have no idea what the problem could be.
Edit: I should note that the C code is very vanilla C, is well-tested and was ported from a working iPhone project. Also, this project is using the Android NDK framework, which lets you run native C code from an Android project from within JNI. However, I don't think that this is strictly an NDK issue... it seems like a JNI setup/initialization error on my part.
You need to create a Java class with the same members as C struct, and 'map' them in the C code via methods env->GetIntField, env->SetIntField, env->GetFloatField, env->SetFloatField, and so on - in short, lots of manual labor, hopefully there already exist programs that do it automatically: JNAerator (http://code.google.com/p/jnaerator) and SWIG (http://www.swig.org/). Both have their pros and cons, the choice is up to you.
It's crashing because Java_com_myorg_MyJavaClass_createNewMyStruct is declared to return jobject, but is actually returning struct MyStruct. If you ran this with CheckJNI enabled, the VM would complain loudly and abort. Your processData() function is also going to be fairly upset about what it gets handed in arguments.
A jobject is an object on the managed heap. It can have extra stuff before or after the declared fields, and the fields don't have to be laid out in memory in any particular order. So you can't map a C struct on top of a Java class.
The most straightforward way to deal with this was identified in an earlier answer: manipulate the jobject with JNI functions. Allocate the objects from Java or with NewObject, Get/Set the object fields with appropriate calls.
There are various ways to "cheat" here. For example, you could include a byte[] in your Java object that holds sizeof(struct MyStruct) bytes and then use GetByteArrayElements to get a pointer to it. A bit ugly, especially if you want to access the fields from the Java side as well.
C structure is the collection of variables (some are function pointer). Pass to java is not a good idea. In general, it is the problem how to pass more complex type to java, like pointer.
In JNI book, to keep the pointer/structure in native and export manipulation to java is recommended. You can read some useful articles. The JavaTM Native Interface Programmer's Guide and Specification, I have read. 9.5 Peer Classes have a solution to deal with it.
Make the class on both the Java and C++ sides, just putting in the member variables. C++ structs are really just classes with public data members. If you are really in pure C, stop reading now.
Use your IDE(s) to make setters and getters for the member variables automatically.
Use javah to generate the C header file from the Java class.
Do some editing on the C++ side to make the setters and getters match the generated header file.
Put in the JNI code.
This is not an ideal solution, but it may save you a little time, and it will at least give you a skeleton that you can edit. This functionality could be added to an IDE, but without a big demand, it probably won't happen. Most IDEs don't even support mixed language projects, let alone having them talk to each other.
I'm coming from the world of c#.
in C# i am able to use the class dynamic http://msdn.microsoft.com/en-us/library/dd264741.aspx
This allows me to not have to use templated/generic classes but achieve a simliar feel for certian situations.
I'm have been unsuccessfull in internet searchs as unfortunately 'dynamic' and 'java' keywords turn up alot of unrelated infromation on dynamic architectures.
I have dabbled a bit in javaFX and there is a type var which appears to have the same usage as c#'s dynamic. However it doesnt appear to be usable in Java.
thanks,
stephanie
Java doesn't support dynamic typing, but you can simulate something like that using dynamic proxy in Java. First you'll need to declare an interface with operations you want to invoke on your objects:
public interface MyOps {
void foo();
void boo();
}
Then create Proxy for dynamic invocation on myObjectInstance:
MyOps p = (MyOps) Proxy.newProxyInstance(getClass().getClassLoader(), //
new Class<?>[] { MyOps.class }, //
new MyHandler(myObject));
p.foo();
p.boo();
where MyHandler is declared like this:
public class MyHandler implements InvocationHandler {
private final Object o;
public MyHandler(Object o) {
this.o = o;
}
public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {
Method method = o.getClass().getMethod(m.getName(), m.getParameterTypes());
return method.invoke(o, args);
}
}
so, if myObject has methods foo() and boo(), they will be invoked, or else, you'll get a RuntimeException.
There is also number of languages that can run in JVM support dynamic typing, e.g. Scala, Groovy, JRuby, BeanShell, JavaScript/Rhino and many others. There is some JVM changes are coming in Java 7 to support a native dynamic dispatch, so these languages could perform much better, but such feature won't be directly exposed in statically typed Java language.
There is nothing like that in Java
There's nothing equivalent in Java. The closest thing you could do is declare a variable of type Object but then you have to cast that variable to whatever you're expecting in order to invoke any method on it that's not implemented by Object (or use reflection but that's sloooow).
Java is a strongly typed language. I think for the next version there will be some dynamic typing, to allow for closures, but that's next year or more probably 2012.
In Groovy you can just use "def" to declare a variable without a type, and the type will be resolved at runtime. And you can compile the Groovy code to Java bytecode...
You can also include Scala code, which does not require explicit type declarations. Scala produces Java byte code. I haven't used C#, so I'm afraid I can't take this comment to the point of responding directly to the question. Maybe someone else can add to it.
I'm currently using both C++ and Java in a project and I'd like to be able to send an object which is contained in C++ to my Java interface in order to modify it via a GUI and then send the modification back in C++.
So far I've been returning either nothing, an int or a boolean to Java via the JNI interface. This time I have to send an object through the interface. I have made similar class definition available both in C++ and in Java. I'd like to know how I'd go about creating the object so that I can use it in Java.
In C++ I have:
JNIEXPORT MyObject JNICALL Java_ca_X_Y_Z_C_1getMyObject(JNIEnv* env, jclass, jint number);
This function would get called by Java in order to get the object from the C++ side (the object is contained in a singleton, easily accessible).
On the Java end, I do a simple call to this method,
MyObject anObject = C_getMyObject(3);
which should return me the newly created object.
Java currently returns me a UnsatisfiedLinkError when I do the actual call. What is wrong?
Here's the solution I opted to use:
First, I would create a similar object in Java. Then, from C++ I would instanciate it and pass it all the values.
(C++)
clazz = env->FindClass("java/lang/Integer");
jmethodID method = env->GetMethodID(clazz, "<init>", "(I)V");
return env->NewObject(clazz, method, (jint)anInteger);
But then I realised this wasn't very portable and was a bit too complicated.
Instead, I decided to return a string that Java would parse and use to initialize the object on its side.
(JAVA)
String aString = "valuesoftheobject";
MyObject myObject(aString);
MyObject would have a constructor which takes a string. I believe the solution is simple and effective.
Another tool you should look at is SWIG. SWIG is a great tool for generate wrappers in other languages (such as Java, Python or C#) for existing C/C++ objects. It will generate automatic Java wrappers around C/C++ objects, and do all the heavy JNI lifting for you.
I use it extensively in Xuggler. To see an example, if you download the Xuggler source code there is a C++ object here:
csrc/com/xuggle/xuggler/IStreamCoder.h
I define a SWIG interface file here:
csrc/com/xuggle/xuggler/IStreamCoder.i
And when run through Swig it generates a Java object (which is stored here)
generate/java/com/xuggle/xuggler/IStreamCoder.java
We can then access that object from Java easily (well, I add some ref counting stuff, but that's pretty advanced). Hope that helps.
Art
If your MyObject class is defined in C++, you're not going to be able access its methods in Java. I'd try to define a Java wrapper class around your C object:
Java:
public C_Object() {
handle = createHandle();
}
private native long createHandle(); // or whatever pointer/handle type?
public void doStuff() {
_doStuff(handle);
}
private native void _doStuff(long handle);
If you can extrapolate a C api instead, you might try JNA.
Your UnsatisfiedLinkError may be the extra character in your function name as written above, or perhaps it can't handle the MyObject return value?