26

I got an application written in C++ and I am able to extend the applications functionality by writing plugins in C++ for it.

What I basically want to do is to embed Java into this application. This has already been done with Python (not done by me).

I read something about JNI but there is always the speech from a full programm that uses Java classes.

What I'd like to do is, to use classes from C++ in Java to interact with the application.
It's a 3D app in this case, called Cinema 4D.

Is there a way to compile and evaluate Java code while the application is running (in some sort of scripting language) using JNI or anything like it ?

Example imaginary code after the embedding was done:

import c4d.documents.*;

class Main {
  public static void main() {
    BaseDocument doc = GetActiveDocument();
    BaseObject op = doc.GetActiveObject();
    if (op != null) {
      op.Remove();
    }
  }
}

This code should interact with Cinema 4D to delete the selected object.

6
  • Do you need full java SE or just some minimal VM? Sep 21, 2011 at 20:44
  • Why do you say "some sort of scripting language", if you've already determined that this language must be Java?
    – jalf
    Sep 21, 2011 at 20:45
  • @MichałŠrajer This is actually still open, basic interaction between Java and the application would be great for the beginning.
    – Niklas R
    Sep 21, 2011 at 20:50
  • @jalf: There shouldn't be the need to restart the application in order to run newly added Java code, I want to write an 'IDE' within C4D where you can run the code directly
    – Niklas R
    Sep 21, 2011 at 20:51
  • @NiklasR - "basic interaction" sounds like a great job for a socket.
    – Flexo
    Sep 21, 2011 at 21:02

6 Answers 6

53

You can embed a JVM within your application. Oracle's official reference book has some more details. The synopsis of it is:

#include <jni.h>       /* where everything is defined */

int main() {
  JavaVM *jvm;       /* denotes a Java VM */
  JNIEnv *env;       /* pointer to native method interface */
  JDK1_1InitArgs vm_args; /* JDK 1.1 VM initialization arguments */
  vm_args.version = 0x00010001; /* New in 1.1.2: VM version */
  /* Get the default initialization arguments and set the class 
   * path */
  JNI_GetDefaultJavaVMInitArgs(&vm_args);
  vm_args.classpath = ...;
  /* load and initialize a Java VM, return a JNI interface 
   * pointer in env */
  JNI_CreateJavaVM(&jvm, &env, &vm_args);
  /* invoke the Main.test method using the JNI */
  jclass cls = env->FindClass("Main");
  jmethodID mid = env->GetStaticMethodID(cls, "test", "(I)V");
  env->CallStaticVoidMethod(cls, mid, 100);
  /* We could have created an Object and called methods on it instead */
  /* We are done. */
  jvm->DestroyJavaVM();
}

You can do far more sophisticated things if you want (e.g. custom class loaders) but that's about it in terms of the bare minimum needed to get a JVM working within your application.

3
  • Now, isn't this for calling a Java method from C++ ? I'd actually need it the other way round :)
    – Niklas R
    Sep 22, 2011 at 18:20
  • 4
    With swig you can generate bindings that let you make calls to C++ from java. The question implied you wanted it this way though. You can also do both in one program.
    – Flexo
    Sep 22, 2011 at 19:27
  • My two cents: since OP wants to load plugins, I think he should also read about how custom class loaders allows him to read a "plugin jar". Also, you need Java classes with native methods (ie JNI) to call C++ from Java. Feb 9, 2016 at 19:47
4

There seems to be some confusion over whether you want to embed Java into the C++ app or the other way around. I will take each case.

  1. For embedding java into c++ app, you can make a socket call to the java program. On java end, you use SocketServer and on the C++ end, you use the General Socket Layer library. This is by far the easiest and most scalable approach. As your java workload keeps increasing, you keep adding additional jvm. Slightly complicated to deploy but, it works really well.

  2. For embedding C++ app in java. This is simple. You compile C++ app into a shared library and use JNI to invoke it.

2

What I basically want to do is to embed Java into this application. This has already been done with Python (not done by me).

The JNI Invocation API supports this, as described by @awoodland. Here's a current link, for Java 6/7.

What I'd like to do is, to use classes from C++ in Java to interact with the application. It's a 3D app in this case, called Cinema 4D.

For this you could use one of the following:

  • Java native methods implemented in C
  • JNA
  • SWIG

Is there a way to compile and evaluate Java code while the application is running (in some sort of scripting language) using JNI or anything like it ?

BeanShell or Groovy, among others, might be of interest to you. Both support dynamically interpreted code that runs on the JVM.

1
  • To call C++ from Java, I would recommend to also have a look at BridJ + JNAerator.
    – zOlive
    Sep 22, 2011 at 11:12
1

I've been working in something similar lately. What worked for me was using the library jni.h that comes when you install java (Java\jdk[version]\include) and creating a dll with c/c++ code in visual studio. For example:

Test.h

//declare the method you want to implement in c/c++ in the header
//include the jni header
#include <jni.h>
JNIEXPORT void JNICALL Java_Test_print(JNIEnv *, jobject);
//Java_[Class Name]_[Method Name](pointer to JVM, java object);

Test.cpp

extern "C" JNIEXPORT void JNICALL Java_WinampController_printTrackInfo (JNIEnv *env, jobject obj){
    printf("Hey, I'm a java method in c (or not?)\n");
}

Then create a dll with Visual Studio and load the dll within a static block. I didn't try that without compiling the c/c++ code in a dll, maybe there's another way to call the c/c++ code. But that's how you implement it.

Test.java

//declare the same method native inside a class in java
public class Test{
    static {
        System.loadLibrary("Test"); //load the dll
    }
    public native void print();
} //after that you just call test.print() normally

So, you just do that and implement java methods with all c/c++ you want.

If you still don't know how to do it, enlighten yourself here:

Java Native Interface Specification - Oracle

Java Native Interface - Wikipedia

0

For the scenario you are describing JNI is probably the best way to go. You would be exposing the functionality of your C++ app as a DLL that can be incorporated into and used from a Java application.

-2

You probably need to rethink your design. Java is not a good choice for this kind of tasks. There is no eval() function in java standard library similar to eval() from python or shell.

You can create a java VM in C++ code using JNI but it's kind of heavy. There is still issue how to create a bytecode from a java source. You will have to embed a lot of code to compile and run java code in C++. Don't do that. There must be better solution.

You can for example use some RPC (SOAP, XML-RPC, Corba) between your C++ code and separate java code. If you need to do some eval()-like java invocation, you can use Groovy or Jython (both has eval(), access to all standard java library and can run regular java classes).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.