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.
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.
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.
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.
For embedding C++ app in java. This is simple. You compile C++ app into a shared library and use JNI to invoke 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).
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.
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
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.
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).
Related
I would like call a Java function from C code without shared library
and without a previous call of some Java function.
I know how to call my Java function, but I need get Env and JavaVM and I realy dont know how I get it. I can't use JNI_CreateJavaVM or JNI_OnLoad because I work on android. I'm using android-ndk-r13b to build the C code.
I'm algo using Eclipse Juno.
How could I solve this?
From my usage of NDK, you can call the JNI_OnLoad function from android. From there you can call any class you want using a static method or through an instance object.
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv* env;
if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
return -1;
}
return JNI_VERSION_1_6;
}
The best approach you could have in my opinion is using a RESTful API in your Java code, so your C code could access the function via JSON requests/responses. It would be helpful if you explain why you need the code in C. Is the C code in a separate project or is it generated by your Java code?
This is my first time working with DLL's and I am at a bit of a loss.
Not because I don't understand the code. But because all of the tutorials Im following and they are breaking at some points.
First I attempted this, but my work was cut short when the javah command would not work erroring out with the message: Error: Could not find or load main class com.sun.tools.javah.Main
I then moved on to make my own ddl's so that I can call them from C a library. Found this video and I was able to follow it and its page on the Microsoft page to make the dll. Note that I am fully capable of following the example. The one part that I struggle with is what happens if I don't have the header file or a lib file to the DLL. So then I started following this example and visual studios is saying that import my not exist.
I found that others were able to get the same exact thing working.
What am I doing wrong? End goal, I'd like to know how to create a DLL file like in the video. And only with the DLL file in my possession, access its functions.
So if the DLL was created with the following:
Header
namespace nmspace
{
class myclass{
public:
static __declspec(dllexport) void Crap();
};
}
Source.cpp
#include "Header.h"
using namespace std;
#include <iostream>
namespace nmspace
{
void myclass::Crap(){
cout << "Some Crap";
}
}
How would I call it via LoadLibarary or LoadLibararyA. Note that this did not work for me
To read the dll:
#include <Windows.h>
#include <iostream>
using namespace std;
void PrintFullPath(char * partialPath)
{
char full[_MAX_PATH];
if (_fullpath(full, partialPath, _MAX_PATH) != NULL)
printf("Full path is: %s\n", full);
else
printf("Invalid path\n");
}
int main(){
HMODULE hMod = LoadLibrary("SimpleDLL.dll");
if (NULL == hMod)
{
cout << "LoadLibrary failed\n";
PrintFullPath(".\\");
system("PAUSE");
return 1;
}
}
In the above code, I print out the current working directory. In that directory I have placed my dll. Still the dll is not being loaded.
I am using Visual Studios if that matter. I would also be intrested to see how I would compile the above c++ code via command line and include the dll with it!
EDIT:
I also found this but it relys on the header file as well. Note that I will know what the function names and formats are through the documentation. I just have no header file!
DLLs created with C# are not like other DLLs. They are technically called .NET assemblies. They rely on the Common Language Runtime (CLR) in the same way that Java bytecode relies on the Java Virtual Machine. The video you posted a link to is not creating a .NET assembly, but rather a native Windows DLL.
Obviously, if you have two virtual machines loaded in a process, things are going to get complicated. They both have their own ideas about how to use memory, garbage collection, layout of objects in memory, threading and so on.
That's not to say that what you are trying to do is impossible, but it's a lot more complicated than loading native libraries with LoadLibrary.
You might like to take a look at the following projects to help you out:
SWiG - www.swig.org - free but I'm not sure how much extra work will be involved in interfacing Java to C#
JNbridge - www.jnbridge.com - not free but claims to make what you are trying to do simple
Javonet - www.javonet.com - not free but claims to make what you are trying to do simple
IKVM - www.ikvm.net - this one is a bit left-field. It lets you run Java bytecode on a .NET runtime, which then means that you can call .NET/C# code directly. If you Java is fairly simple and/or you don't have to deploy your code to many clients, this might work for you.
I am creating a GUI using Jython. I want to program my logic in C. How could I can call a C Function from my Python Code. Sorry if this a newbie question, but I have never worked with linking files except Sparc Assembly from C.
Jython cannot use ctypes, or C extension modules (whether built manually, or with Cython, or otherwise).
The way to do this is the same way as in Java: Through a JNI bridge.
First, you write a C++ wrapper that talks to the so, and uses functions from <jni.h> to implement functions like this:
JNIEXPORT void JNICALL _PACKAGE(bar)(JNIEnv *env, jclass cls, jint i) {
if (bar(i)) {
throwPyFromErrno(env, OSError);
}
}
Next, in Java, you define a public class full of Java wrappers around those C++ wrappers, like this:
public class foo implements InitModule {
public final static native void bar(int i);
}
Finally, in Jython, you can just import the class (which acts like a Python module) from its Java module and use it like any other module:
try:
foo.bar(3)
except OSError as e:
print "Failed:", e
Most of this is standard JNI, but you also have to know things like how to create Jython objects. Ideally, you'll use wrappers for that, so you can just write makePyInteger(env, value) or throwPyFromErrno(env, exctype) instead of doing all the FindClass, GetStaticMethodID, etc. stuff manually.
I don't have any tutorials to recommend. But see jnios for a nice-sized example. The O'Reilly book's Chapter 25. Extending and Embedding Jython seems like it might be a decent primer (although I haven't read it). You'll probably want to read a tutorial on using JNI for Java before trying to tackle Jython.
A different way to solve this problem is to break your single program into two pieces.
The GUI program runs in Jython. When it needs to call the C code, it does that by running a worker program.
The worker program runs in CPython or PyPy, so it can use any of the usual techniques for talking to C libraries: ctypes, cffi, a custom C extension module (maybe using Cython, Boost.Python, SWIG, SIP, …), Weave, etc.
For a simple case, where you just need to call one function, pass it a few strings, and get back a string, it's as trivial as this:
import subprocess
def my_function(*args):
return subprocess.check_output(['python',
'/path/to/worker/script.py'] + args)
(Note that there are a few bugs with subprocess in older versions of Jython, especially on OS X and Windows. If you run into a problem, 2.5.4 and 2.7.0, which are currently in RC and beta stages, respectively, have probably fixed it.)
If you need to make lots of calls one at a time throughout the life of your program, you'll probably want to keep the worker script running in the background, and use some form of RPC to talk to it. This blog post shows how to do it using the bjsonrpc library.
From what I understand, SWIG is to wrap C++/C to make it appear in Java, and javah is to implement certain java functions in C++ ( aka native functions ).
Is there a tool which can create a C++ wrapper over a java class, so that the caller. of this c++
wrapper doesn't have to worry about java, for example
Input Java is
class hw {
public void hi() {
System.out.println("Hello World");
}
}
Tools outputs hw.hh ( and some. c++ files ), which can be used as:
hw *h = new hw(/*JEnv */ env);
h->hi();
Is there a tool available which can do this ?
Options include, the following, in ascending order of expense to you.
Hand-written JNI code written by clients of your Java class.
Hand-written, JNI-driven wrappers written by you for clients of your class.
JACE-generated wrappers. JACE is a free tool. Last version was in 2008; not sure if development is continuing.
JunC++ion-generated wrappers. This commercial library produces the best results with the least development effort. It supports Java callbacks, with C++ classes implementing Java interfaces. The author is very responsive and a very nice guy. However, there is a price tag, and you'll want to be sure about deployment costs.
I used this product a long time ago, http://www.codemesh.com/products/junction/
It will do exactly what you want.
Just a disclaimer, I used it almost 6 years ago. I am not affliated with this product.
I have a Python interface of a graph library written in C - igraph (the name of library). My need is to invoke the python modules pertaining to this graph library from Java code. It goes like this, the core of library is in c. This core has been imported into Python and interfaces to the functions embedded in core are available in Python. My project's rest of the code is in Java and hence I would like to call the graph functions by Java as well.
Jython - which lets you invoke python modules with in Java was an option.I went on trying Jython to discover that it will not work in my case as the core code is in C and Jython wont support anything that is imported as a c dll in python code.I also thought of opting for the approach of calling graph routines directly in c. That is without passing through Python code. I am assuming there must be something which lets you call c code from Java, how ever I am not good in C hence I did not go for it.
My last resort seems to execute Python interpreter from command line using Java. But that is a dirty and shameless. Also to deal with the results produced by Python code I will have to write the results in a file and read it back in java. Again dirty way.
Is there something that any one can suggest me? Thanks to every one giving time.
Thanks Igal for answering. I had a look at it. At first glance it appears as if it is simply calling the python script.
Jep jep = new Jep(false, SCRIPT_PATH, cl);
jep.set("query", query);
jep.runScript(SCRIPT_PATH + file);
jep.close();
Isnt it very similar to what we would do if called the python interpreter from command line through a Java code.
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("python test.py");
Concern is how do I use the results generated by Python script. The naive way is to write them to file and read it back in Java. I am searching for a smarter approach.Thanks for suggestion anyway.
Never tried it. But I recently stumbled on a project named Jepp that may be of interest to you.
Jepp embeds CPython in Java. It is safe to use in a heavily threaded environment, it is quite fast and its stability is a main feature and goal.
If you want to call C functions from Java, JNA (Java Native Access) is probably the way to go. JNA allows you to call functions in native libraries without having to write the C glue code (as you would have to when using JNI), and automatically maps between primitive data types in Java and C. A simple example might look like this:
import com.sun.jna.Native;
import com.sun.jna.Library;
public class PrintfWrapper {
public interface CLibrary extends Library {
CLibrary INSTANCE = (CLibrary)Native.loadLibrary("c", CLibrary.class);
void printf(String formatString, Object... args);
}
public static void main(String[] args) {
CLibrary.INSTANCE.printf("Hello, world\n");
}
}
However, things will get complicated with igraph because igraph uses many data structures that cannot be mapped directly into their Java counterparts. There is a project called JNAerator which should be able to generate the JNA source from igraph's header files, but I have never tried it and chances are that the results will still need some manual tweaking.
Also note that a Java interface for igraph is being developed slowly but steadily and it might become useful in a few months or so.
You can use jep.getValue() to retrieve a value from script's global dictionary.
There are caveats to that concerning scope levels in Python, so most people find it clearer to pass a Java class to python and set the return value in that instance in Python. After the script completes, the Java code will then have the result.
For example:
==> Java
class ReturnValueClass {
public int scriptResult;
};
ReturnValueClass value = new ReturnValueClass();
jep.set("retval", value);
==> Python
# do something
pass
# write the return value
retval.scriptResult = some_python_value
==> Java
System.out.println(value.scriptResult);
Hope that helps,
Mike (I wrote Jep)