JESS: Call Jess from C++ via JNI

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

JESS: Call Jess from C++ via JNI

Hunter Mcmillen
Hello everyone, 

 I am working on a project where I am using a C++ framework and API to create a game agent. My agent has to be flexible so it can react to/predict events that occur inside the game environment, Jess has the kind of flexibility that I need for my agent to be good,  but I am having trouble connecting to Jess from C++ and that is where I was hoping someone could help me out. 

What I am doing right now
I have a C++ program that starts a Java Virtual Machine and searches for a Java class file name "TestJNIJessInvoke"

Inside of "TestJNIJessInvoke.java" I define a simple function in Jess, and try to call that function then print the result
import jess.*;
public class TestJNIJessInvoke
{
    public static void main(String[] args) throws JessException
    {
Rete r = new Rete();
r.executeCommand("(deffunction square (?n) (return (* ?n ?n)))");
Value v = r.executeCommand("(square 3)");

System.out.println(v.intValue(r.getGlobalContext()));
    }
}

But when I try to compile and link the C++ file with:
cl 
   -I"C:\Program Files\Java\jdk1.7.0\include" 
   -I"C:\Program Files\Java\jdk1.7.0\include\win32" 
   TestJNIJessInvoke.cpp 
   -link "C:\Program Files\Java\jdk1.7.0\lib\jvm.lib"

I get a class loader exception:
Exception in thread "main" java.lang.NoClassDefFoundError: jess/Rete
        at TestJNIJessInvoke.main(TestJNIJessInvoke.java:6)
Caused by: java.lang.ClassNotFoundException: jess.Rete
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
        ... 1 more

Exception in thread "main" java.lang.NoClassDefFoundError: jess/Rete
        at TestJNIJessInvoke.main(TestJNIJessInvoke.java:6)
Caused by: java.lang.ClassNotFoundException: jess.Rete
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
        ... 1 more

Questions

1) Is there some other directory that I am supposed to be including that has the .class files for Jess? Right now all I am including is jess.jar
2) Is the general design I have a good idea? or is there a better way to facilitate communication between Jess and C++?



Thanks,
Hunter McMillen

Reply | Threaded
Open this post in threaded view
|

Re: JESS: Call Jess from C++ via JNI

Dusan Sormaz
Hunter,

This is not Jess specific question. JVM simply can not find Java class to load.
Can you show snippet of the C++ code that starts jvm and tries to load TestJNIJessinvoke?

As for overall design, is C++ requirement? Can you do it all in Java?

Dusan Sormaz

On 9/26/2011 8:51 PM, Hunter McMillen wrote:
Hello everyone, 

 I am working on a project where I am using a C++ framework and API to create a game agent. My agent has to be flexible so it can react to/predict events that occur inside the game environment, Jess has the kind of flexibility that I need for my agent to be good,  but I am having trouble connecting to Jess from C++ and that is where I was hoping someone could help me out. 

What I am doing right now
I have a C++ program that starts a Java Virtual Machine and searches for a Java class file name "TestJNIJessInvoke"

Inside of "TestJNIJessInvoke.java" I define a simple function in Jess, and try to call that function then print the result
import jess.*;
public class TestJNIJessInvoke
{
    public static void main(String[] args) throws JessException
    {
Rete r = new Rete();
r.executeCommand("(deffunction square (?n) (return (* ?n ?n)))");
Value v = r.executeCommand("(square 3)");

System.out.println(v.intValue(r.getGlobalContext()));
    }
}

But when I try to compile and link the C++ file with:
cl 
   -I"C:\Program Files\Java\jdk1.7.0\include" 
   -I"C:\Program Files\Java\jdk1.7.0\include\win32" 
   TestJNIJessInvoke.cpp 
   -link "C:\Program Files\Java\jdk1.7.0\lib\jvm.lib"

I get a class loader exception:
Exception in thread "main" java.lang.NoClassDefFoundError: jess/Rete
        at TestJNIJessInvoke.main(TestJNIJessInvoke.java:6)
Caused by: java.lang.ClassNotFoundException: jess.Rete
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
        ... 1 more

Exception in thread "main" java.lang.NoClassDefFoundError: jess/Rete
        at TestJNIJessInvoke.main(TestJNIJessInvoke.java:6)
Caused by: java.lang.ClassNotFoundException: jess.Rete
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
        ... 1 more

Questions

1) Is there some other directory that I am supposed to be including that has the .class files for Jess? Right now all I am including is jess.jar
2) Is the general design I have a good idea? or is there a better way to facilitate communication between Jess and C++?



Thanks,
Hunter McMillen


-- 
***************************************************
* Dusan Sormaz, PhD, Associate Professor
* Ohio University
* Department of Industrial and Systems Engineering
* 284 Stocker Center, Athens, OH 45701-2979
* phone: (740) 593-1545 
* fax:   (740) 593-0778
* e-mail: [hidden email] 
* url: http://oak.cats.ohiou.edu/~sormaz/
***************************************************
Reply | Threaded
Open this post in threaded view
|

RE: JESS: Call Jess from C++ via JNI

Friedman-Hill, Ernest
In reply to this post by Hunter Mcmillen
This is all perfectly reasonable so far. When you create the JVM you'll need to tell it where jess.jar is, along with any other jars you use, with the "-cp" flag or the "java.class.path" property.
 
Once you have this working, you'll presumably want to connect things a little more tightly. You can use the JNI API to write the equivalent of your three-line main() in C++ pretty easily; you'll want to put together a C++ version "executeCommand()" that controls the Rete instance, passes a script along, executes it, and gets the Value back, decoding it as needed.
 


From: [hidden email] [mailto:[hidden email]] On Behalf Of Hunter McMillen
Sent: Monday, September 26, 2011 8:51 PM
To: jess-users
Subject: JESS: Call Jess from C++ via JNI

Hello everyone, 

 I am working on a project where I am using a C++ framework and API to create a game agent. My agent has to be flexible so it can react to/predict events that occur inside the game environment, Jess has the kind of flexibility that I need for my agent to be good,  but I am having trouble connecting to Jess from C++ and that is where I was hoping someone could help me out. 

What I am doing right now
I have a C++ program that starts a Java Virtual Machine and searches for a Java class file name "TestJNIJessInvoke"

Inside of "TestJNIJessInvoke.java" I define a simple function in Jess, and try to call that function then print the result
import jess.*;
public class TestJNIJessInvoke
{
    public static void main(String[] args) throws JessException
    {
Rete r = new Rete();
r.executeCommand("(deffunction square (?n) (return (* ?n ?n)))");
Value v = r.executeCommand("(square 3)");

System.out.println(v.intValue(r.getGlobalContext()));
    }
}

But when I try to compile and link the C++ file with:
cl 
   -I"C:\Program Files\Java\jdk1.7.0\include" 
   -I"C:\Program Files\Java\jdk1.7.0\include\win32" 
   TestJNIJessInvoke.cpp 
   -link "C:\Program Files\Java\jdk1.7.0\lib\jvm.lib"

I get a class loader exception:
Exception in thread "main" java.lang.NoClassDefFoundError: jess/Rete
        at TestJNIJessInvoke.main(TestJNIJessInvoke.java:6)
Caused by: java.lang.ClassNotFoundException: jess.Rete
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
        ... 1 more

Exception in thread "main" java.lang.NoClassDefFoundError: jess/Rete
        at TestJNIJessInvoke.main(TestJNIJessInvoke.java:6)
Caused by: java.lang.ClassNotFoundException: jess.Rete
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
        ... 1 more

Questions

1) Is there some other directory that I am supposed to be including that has the .class files for Jess? Right now all I am including is jess.jar
2) Is the general design I have a good idea? or is there a better way to facilitate communication between Jess and C++?



Thanks,
Hunter McMillen

Reply | Threaded
Open this post in threaded view
|

Re: JESS: Call Jess from C++ via JNI

Hunter Mcmillen
In reply to this post by Dusan Sormaz
Well the framework and API I am using are very large, so much so that it would be unreasonable to rewrite them in Java. Sorry for the somewhat unspecific question? Really I wanted to know why the class loader couldn't find the jess.Rete class, when I have jess.jar on my classpath, and have it in the directory where the c++ program executes.

Here is the c++ code where I create the JVM:

#include <jni.h>
#include <cstdlib>
using namespace std;
int main() 
{
     JNIEnv *env;
     JavaVM *jvm;
     jint res;
     jclass cls;
     jmethodID mid;
     jstring jstr;
     jclass stringClass;
     jobjectArray args;
 
     JavaVMInitArgs vm_args; /* JDK/JRE 6 VM initialization arguments */
     JavaVMOption* options = new JavaVMOption[1];
     options[0].optionString = (char*)&"-Djava.class.path=.";  //the current directory is where jess.jar is also
     vm_args.version = JNI_VERSION_1_6;
     vm_args.nOptions = 1;
     vm_args.options = options;
     vm_args.ignoreUnrecognized = false;

     /* load and initialize a Java VM, return a JNI interface
      * pointer in env */
     JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
     cls              = env->FindClass("TestJNIJessInvoke");
     mid            = env->GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V");
     jstr             = env->NewStringUTF("");
     stringClass = env->FindClass("java/lang/String");
     args           = env->NewObjectArray(1, stringClass, jstr);

     env->CallStaticVoidMethod(cls, mid, args);
 
     if (env->ExceptionOccurred()) 
     {
env->ExceptionDescribe();
     }
     jvm->DestroyJavaVM();
}


On Tue, Sep 27, 2011 at 11:58 AM, Dusan Sormaz <[hidden email]> wrote:
Hunter,

This is not Jess specific question. JVM simply can not find Java class to load.
Can you show snippet of the C++ code that starts jvm and tries to load TestJNIJessinvoke?

As for overall design, is C++ requirement? Can you do it all in Java?

Dusan Sormaz


On 9/26/2011 8:51 PM, Hunter McMillen wrote:
Hello everyone, 

 I am working on a project where I am using a C++ framework and API to create a game agent. My agent has to be flexible so it can react to/predict events that occur inside the game environment, Jess has the kind of flexibility that I need for my agent to be good,  but I am having trouble connecting to Jess from C++ and that is where I was hoping someone could help me out. 

What I am doing right now
I have a C++ program that starts a Java Virtual Machine and searches for a Java class file name "TestJNIJessInvoke"

Inside of "TestJNIJessInvoke.java" I define a simple function in Jess, and try to call that function then print the result
import jess.*;
public class TestJNIJessInvoke
{
    public static void main(String[] args) throws JessException
    {
Rete r = new Rete();
r.executeCommand("(deffunction square (?n) (return (* ?n ?n)))");
Value v = r.executeCommand("(square 3)");

System.out.println(v.intValue(r.getGlobalContext()));
    }
}

But when I try to compile and link the C++ file with:
cl 
   -I"C:\Program Files\Java\jdk1.7.0\include" 
   -I"C:\Program Files\Java\jdk1.7.0\include\win32" 
   TestJNIJessInvoke.cpp 
   -link "C:\Program Files\Java\jdk1.7.0\lib\jvm.lib"

I get a class loader exception:
Exception in thread "main" java.lang.NoClassDefFoundError: jess/Rete
        at TestJNIJessInvoke.main(TestJNIJessInvoke.java:6)
Caused by: java.lang.ClassNotFoundException: jess.Rete
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
        ... 1 more

Exception in thread "main" java.lang.NoClassDefFoundError: jess/Rete
        at TestJNIJessInvoke.main(TestJNIJessInvoke.java:6)
Caused by: java.lang.ClassNotFoundException: jess.Rete
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
        ... 1 more

Questions

1) Is there some other directory that I am supposed to be including that has the .class files for Jess? Right now all I am including is jess.jar
2) Is the general design I have a good idea? or is there a better way to facilitate communication between Jess and C++?



Thanks,
Hunter McMillen


-- 
***************************************************
* Dusan Sormaz, PhD, Associate Professor
* Ohio University
* Department of Industrial and Systems Engineering
* 284 Stocker Center, Athens, OH 45701-2979
* phone: <a href="tel:%28740%29%20593-1545" value="+17405931545" target="_blank">(740) 593-1545 
* fax:&nbsp;&nbsp; <a href="tel:%28740%29%20593-0778" value="+17405930778" target="_blank">(740) 593-0778
* e-mail: [hidden email] 
* url: http://oak.cats.ohiou.edu/~sormaz/
***************************************************

Reply | Threaded
Open this post in threaded view
|

RE: JESS: Call Jess from C++ via JNI

Friedman-Hill, Ernest
The problem is here. The Java classpath doesn't list directories in which jar files can be found, but rather, the jar files themselves. The argument should be, e.g., "-Djava.class.path=./jess.jar". 
 
      options[0].optionString = (char*)&"-Djava.class.path=.";  //the current directory is where jess.jar is also 
 
Reply | Threaded
Open this post in threaded view
|

Re: JESS: Call Jess from C++ via JNI

Dusan Sormaz
Thanks Ernest!

I was on the phone call, so you overran me. :-)

Dusan Sormaz

On 9/27/2011 1:31 PM, Friedman-Hill, Ernest wrote:
The problem is here. The Java classpath doesn't list directories in which jar files can be found, but rather, the jar files themselves. The argument should be, e.g., "-Djava.class.path=./jess.jar". 
 
      options[0].optionString = (char*)&"-Djava.class.path=.";  //the current directory is where jess.jar is also 
 


-- 
***************************************************
* Dusan Sormaz, PhD, Associate Professor
* Ohio University
* Department of Industrial and Systems Engineering
* 284 Stocker Center, Athens, OH 45701-2979
* phone: (740) 593-1545 
* fax: (740) 593-0778
* e-mail: [hidden email] 
* url: http://www.ohio.edu/people/sormaz
***************************************************
Reply | Threaded
Open this post in threaded view
|

Re: JESS: Call Jess from C++ via JNI

Hunter Mcmillen
In reply to this post by Friedman-Hill, Ernest
Thanks a lot! That was exactly what was going wrong.

Hunter

On Tue, Sep 27, 2011 at 1:31 PM, Friedman-Hill, Ernest <[hidden email]> wrote:
The problem is here. The Java classpath doesn't list directories in which jar files can be found, but rather, the jar files themselves. The argument should be, e.g., "-Djava.class.path=./jess.jar". 
 
      options[0].optionString = (char*)&"-Djava.class.path=.";  //the current directory is where jess.jar is also 
 

Reply | Threaded
Open this post in threaded view
|

Re: JESS: Call Jess from C++ via JNI

Hunter Mcmillen
In reply to this post by Friedman-Hill, Ernest
Sorry to pester you with more questions.

The way I am currently doing things in invoking a JVM from C++ to call Java code that calls/interacts with Jess code, but it turns out that someone has actually created a java native interface for the api/framework I am using to make my agent, using this I think I can only interact with Jess in my Java program then pass data from my Java code to C++, I was wondering if you thought this would be a better solution than invoke a JVM from C++

Thanks
Hunter

On Tue, Sep 27, 2011 at 12:03 PM, Friedman-Hill, Ernest <[hidden email]> wrote:
This is all perfectly reasonable so far. When you create the JVM you'll need to tell it where jess.jar is, along with any other jars you use, with the "-cp" flag or the "java.class.path" property.
 
Once you have this working, you'll presumably want to connect things a little more tightly. You can use the JNI API to write the equivalent of your three-line main() in C++ pretty easily; you'll want to put together a C++ version "executeCommand()" that controls the Rete instance, passes a script along, executes it, and gets the Value back, decoding it as needed.
 


From: [hidden email] [mailto:[hidden email]] On Behalf Of Hunter McMillen
Sent: Monday, September 26, 2011 8:51 PM
To: jess-users
Subject: JESS: Call Jess from C++ via JNI

Hello everyone, 

 I am working on a project where I am using a C++ framework and API to create a game agent. My agent has to be flexible so it can react to/predict events that occur inside the game environment, Jess has the kind of flexibility that I need for my agent to be good,  but I am having trouble connecting to Jess from C++ and that is where I was hoping someone could help me out. 

What I am doing right now
I have a C++ program that starts a Java Virtual Machine and searches for a Java class file name "TestJNIJessInvoke"

Inside of "TestJNIJessInvoke.java" I define a simple function in Jess, and try to call that function then print the result
import jess.*;
public class TestJNIJessInvoke
{
    public static void main(String[] args) throws JessException
    {
Rete r = new Rete();
r.executeCommand("(deffunction square (?n) (return (* ?n ?n)))");
Value v = r.executeCommand("(square 3)");

System.out.println(v.intValue(r.getGlobalContext()));
    }
}

But when I try to compile and link the C++ file with:
cl 
   -I"C:\Program Files\Java\jdk1.7.0\include" 
   -I"C:\Program Files\Java\jdk1.7.0\include\win32" 
   TestJNIJessInvoke.cpp 
   -link "C:\Program Files\Java\jdk1.7.0\lib\jvm.lib"

I get a class loader exception:
Exception in thread "main" java.lang.NoClassDefFoundError: jess/Rete
        at TestJNIJessInvoke.main(TestJNIJessInvoke.java:6)
Caused by: java.lang.ClassNotFoundException: jess.Rete
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
        ... 1 more

Exception in thread "main" java.lang.NoClassDefFoundError: jess/Rete
        at TestJNIJessInvoke.main(TestJNIJessInvoke.java:6)
Caused by: java.lang.ClassNotFoundException: jess.Rete
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
        ... 1 more

Questions

1) Is there some other directory that I am supposed to be including that has the .class files for Jess? Right now all I am including is jess.jar
2) Is the general design I have a good idea? or is there a better way to facilitate communication between Jess and C++?



Thanks,
Hunter McMillen


Reply | Threaded
Open this post in threaded view
|

Re: JESS: Call Jess from C++ via JNI

soc.frangis
What framework are you using? Curious to see how it is invoking JNI.

"using this I think I can only interact with Jess in my Java program then pass data from my Java code to C++"
-Unless your framework has an API supporting JESS specifically, i doubt that is the case.  It should be providing a 'simpler' implementation to access your java classes but that would just eliminate the cryptic path declaration and still give you an interface to what youre playing with.

Overall opinion, given the chance that your framework may inhibit full controll of the Rete engine or using JESS (and for the learning experience) i would recommend sticking with your current implementation.  Rule engines require precise attention to detail and i wouldn't risk the chance of losing fidelity.

On Wed, Sep 28, 2011 at 2:22 PM, Hunter McMillen <[hidden email]> wrote:
Sorry to pester you with more questions.

The way I am currently doing things in invoking a JVM from C++ to call Java code that calls/interacts with Jess code, but it turns out that someone has actually created a java native interface for the api/framework I am using to make my agent, using this I think I can only interact with Jess in my Java program then pass data from my Java code to C++, I was wondering if you thought this would be a better solution than invoke a JVM from C++

Thanks
Hunter


On Tue, Sep 27, 2011 at 12:03 PM, Friedman-Hill, Ernest <[hidden email]> wrote:
This is all perfectly reasonable so far. When you create the JVM you'll need to tell it where jess.jar is, along with any other jars you use, with the "-cp" flag or the "java.class.path" property.
 
Once you have this working, you'll presumably want to connect things a little more tightly. You can use the JNI API to write the equivalent of your three-line main() in C++ pretty easily; you'll want to put together a C++ version "executeCommand()" that controls the Rete instance, passes a script along, executes it, and gets the Value back, decoding it as needed.
 


From: [hidden email] [mailto:[hidden email]] On Behalf Of Hunter McMillen
Sent: Monday, September 26, 2011 8:51 PM
To: jess-users
Subject: JESS: Call Jess from C++ via JNI

Hello everyone, 

 I am working on a project where I am using a C++ framework and API to create a game agent. My agent has to be flexible so it can react to/predict events that occur inside the game environment, Jess has the kind of flexibility that I need for my agent to be good,  but I am having trouble connecting to Jess from C++ and that is where I was hoping someone could help me out. 

What I am doing right now
I have a C++ program that starts a Java Virtual Machine and searches for a Java class file name "TestJNIJessInvoke"

Inside of "TestJNIJessInvoke.java" I define a simple function in Jess, and try to call that function then print the result
import jess.*;
public class TestJNIJessInvoke
{
    public static void main(String[] args) throws JessException
    {
Rete r = new Rete();
r.executeCommand("(deffunction square (?n) (return (* ?n ?n)))");
Value v = r.executeCommand("(square 3)");

System.out.println(v.intValue(r.getGlobalContext()));
    }
}

But when I try to compile and link the C++ file with:
cl 
   -I"C:\Program Files\Java\jdk1.7.0\include" 
   -I"C:\Program Files\Java\jdk1.7.0\include\win32" 
   TestJNIJessInvoke.cpp 
   -link "C:\Program Files\Java\jdk1.7.0\lib\jvm.lib"

I get a class loader exception:
Exception in thread "main" java.lang.NoClassDefFoundError: jess/Rete
        at TestJNIJessInvoke.main(TestJNIJessInvoke.java:6)
Caused by: java.lang.ClassNotFoundException: jess.Rete
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
        ... 1 more

Exception in thread "main" java.lang.NoClassDefFoundError: jess/Rete
        at TestJNIJessInvoke.main(TestJNIJessInvoke.java:6)
Caused by: java.lang.ClassNotFoundException: jess.Rete
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
        ... 1 more

Questions

1) Is there some other directory that I am supposed to be including that has the .class files for Jess? Right now all I am including is jess.jar
2) Is the general design I have a good idea? or is there a better way to facilitate communication between Jess and C++?



Thanks,
Hunter McMillen





--
V/R
-Socrates Frangis
-Mathematician & Software Engineer
Reply | Threaded
Open this post in threaded view
|

Re: JESS: Call Jess from C++ via JNI

Hunter Mcmillen
Well I am trying to create an agent to compete in the Starcraft AI competition for next year, the API that the agents all use is called BWAPI: http://code.google.com/p/bwapi/, but this is also a standard library that some of the agents use that would be really useful for for my agent called BWSAL: http://code.google.com/p/bwsal/. Anyway there is a native interface that someone created for BWAPI, which I was planning on using in my code, so my plan was to create a native interface for BWSAL, that way I could do all the Jess interaction inside of Java, then call associated methods in C++ via JNI. Does this sound far-fetched? 

On Thu, Sep 29, 2011 at 5:10 PM, Socrates Frangis <[hidden email]> wrote:
What framework are you using? Curious to see how it is invoking JNI.


"using this I think I can only interact with Jess in my Java program then pass data from my Java code to C++"
-Unless your framework has an API supporting JESS specifically, i doubt that is the case.  It should be providing a 'simpler' implementation to access your java classes but that would just eliminate the cryptic path declaration and still give you an interface to what youre playing with.

Overall opinion, given the chance that your framework may inhibit full controll of the Rete engine or using JESS (and for the learning experience) i would recommend sticking with your current implementation.  Rule engines require precise attention to detail and i wouldn't risk the chance of losing fidelity.


On Wed, Sep 28, 2011 at 2:22 PM, Hunter McMillen <[hidden email]> wrote:
Sorry to pester you with more questions.

The way I am currently doing things in invoking a JVM from C++ to call Java code that calls/interacts with Jess code, but it turns out that someone has actually created a java native interface for the api/framework I am using to make my agent, using this I think I can only interact with Jess in my Java program then pass data from my Java code to C++, I was wondering if you thought this would be a better solution than invoke a JVM from C++

Thanks
Hunter


On Tue, Sep 27, 2011 at 12:03 PM, Friedman-Hill, Ernest <[hidden email]> wrote:
This is all perfectly reasonable so far. When you create the JVM you'll need to tell it where jess.jar is, along with any other jars you use, with the "-cp" flag or the "java.class.path" property.
 
Once you have this working, you'll presumably want to connect things a little more tightly. You can use the JNI API to write the equivalent of your three-line main() in C++ pretty easily; you'll want to put together a C++ version "executeCommand()" that controls the Rete instance, passes a script along, executes it, and gets the Value back, decoding it as needed.
 


From: [hidden email] [mailto:[hidden email]] On Behalf Of Hunter McMillen
Sent: Monday, September 26, 2011 8:51 PM
To: jess-users
Subject: JESS: Call Jess from C++ via JNI

Hello everyone, 

 I am working on a project where I am using a C++ framework and API to create a game agent. My agent has to be flexible so it can react to/predict events that occur inside the game environment, Jess has the kind of flexibility that I need for my agent to be good,  but I am having trouble connecting to Jess from C++ and that is where I was hoping someone could help me out. 

What I am doing right now
I have a C++ program that starts a Java Virtual Machine and searches for a Java class file name "TestJNIJessInvoke"

Inside of "TestJNIJessInvoke.java" I define a simple function in Jess, and try to call that function then print the result
import jess.*;
public class TestJNIJessInvoke
{
    public static void main(String[] args) throws JessException
    {
Rete r = new Rete();
r.executeCommand("(deffunction square (?n) (return (* ?n ?n)))");
Value v = r.executeCommand("(square 3)");

System.out.println(v.intValue(r.getGlobalContext()));
    }
}

But when I try to compile and link the C++ file with:
cl 
   -I"C:\Program Files\Java\jdk1.7.0\include" 
   -I"C:\Program Files\Java\jdk1.7.0\include\win32" 
   TestJNIJessInvoke.cpp 
   -link "C:\Program Files\Java\jdk1.7.0\lib\jvm.lib"

I get a class loader exception:
Exception in thread "main" java.lang.NoClassDefFoundError: jess/Rete
        at TestJNIJessInvoke.main(TestJNIJessInvoke.java:6)
Caused by: java.lang.ClassNotFoundException: jess.Rete
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
        ... 1 more

Exception in thread "main" java.lang.NoClassDefFoundError: jess/Rete
        at TestJNIJessInvoke.main(TestJNIJessInvoke.java:6)
Caused by: java.lang.ClassNotFoundException: jess.Rete
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
        ... 1 more

Questions

1) Is there some other directory that I am supposed to be including that has the .class files for Jess? Right now all I am including is jess.jar
2) Is the general design I have a good idea? or is there a better way to facilitate communication between Jess and C++?



Thanks,
Hunter McMillen





--
V/R
-Socrates Frangis
-Mathematician & Software Engineer

Reply | Threaded
Open this post in threaded view
|

RE: JESS: Call Jess from C++ via JNI

Friedman-Hill, Ernest
 To restate: you have three libraries you want to use:
   
    - One (Jess) is written in Java;
 
    - One (BWAPI) can be accessed from Java by using an existing JNI interface,
 
    - And the third (BWSAL) is currently available only in native code. 
 
Your current plan is to write a JNI wrapper for some or all of BWSAL and write your application in Java. This makes perfect sense to me.
 
It might be even easier to use JNA (http://jna.java.net/) instead of writing a specific wrapper, but that depends on various details. Worth looking at, anyway.
 

From: [hidden email] [mailto:[hidden email]] On Behalf Of Hunter McMillen
Sent: Saturday, October 01, 2011 12:52 PM
To: jess-users
Subject: Re: JESS: Call Jess from C++ via JNI

Well I am trying to create an agent to compete in the Starcraft AI competition for next year, the API that the agents all use is called BWAPI: http://code.google.com/p/bwapi/, but this is also a standard library that some of the agents use that would be really useful for for my agent called BWSAL: http://code.google.com/p/bwsal/. Anyway there is a native interface that someone created for BWAPI, which I was planning on using in my code, so my plan was to create a native interface for BWSAL, that way I could do all the Jess interaction inside of Java, then call associated methods in C++ via JNI. Does this sound far-fetched? 

On Thu, Sep 29, 2011 at 5:10 PM, Socrates Frangis <[hidden email]> wrote:
What framework are you using? Curious to see how it is invoking JNI.


"using this I think I can only interact with Jess in my Java program then pass data from my Java code to C++"
-Unless your framework has an API supporting JESS specifically, i doubt that is the case.  It should be providing a 'simpler' implementation to access your java classes but that would just eliminate the cryptic path declaration and still give you an interface to what youre playing with.

Overall opinion, given the chance that your framework may inhibit full controll of the Rete engine or using JESS (and for the learning experience) i would recommend sticking with your current implementation.  Rule engines require precise attention to detail and i wouldn't risk the chance of losing fidelity.


On Wed, Sep 28, 2011 at 2:22 PM, Hunter McMillen <[hidden email]> wrote:
Sorry to pester you with more questions.

The way I am currently doing things in invoking a JVM from C++ to call Java code that calls/interacts with Jess code, but it turns out that someone has actually created a java native interface for the api/framework I am using to make my agent, using this I think I can only interact with Jess in my Java program then pass data from my Java code to C++, I was wondering if you thought this would be a better solution than invoke a JVM from C++

Thanks
Hunter


On Tue, Sep 27, 2011 at 12:03 PM, Friedman-Hill, Ernest <[hidden email]> wrote:
This is all perfectly reasonable so far. When you create the JVM you'll need to tell it where jess.jar is, along with any other jars you use, with the "-cp" flag or the "java.class.path" property.
 
Once you have this working, you'll presumably want to connect things a little more tightly. You can use the JNI API to write the equivalent of your three-line main() in C++ pretty easily; you'll want to put together a C++ version "executeCommand()" that controls the Rete instance, passes a script along, executes it, and gets the Value back, decoding it as needed.
 


From: [hidden email] [mailto:[hidden email]] On Behalf Of Hunter McMillen
Sent: Monday, September 26, 2011 8:51 PM
To: jess-users
Subject: JESS: Call Jess from C++ via JNI

Hello everyone, 

 I am working on a project where I am using a C++ framework and API to create a game agent. My agent has to be flexible so it can react to/predict events that occur inside the game environment, Jess has the kind of flexibility that I need for my agent to be good,  but I am having trouble connecting to Jess from C++ and that is where I was hoping someone could help me out. 

What I am doing right now
I have a C++ program that starts a Java Virtual Machine and searches for a Java class file name "TestJNIJessInvoke"

Inside of "TestJNIJessInvoke.java" I define a simple function in Jess, and try to call that function then print the result
import jess.*;
public class TestJNIJessInvoke
{
    public static void main(String[] args) throws JessException
    {
Rete r = new Rete();
r.executeCommand("(deffunction square (?n) (return (* ?n ?n)))");
Value v = r.executeCommand("(square 3)");

System.out.println(v.intValue(r.getGlobalContext()));
    }
}

But when I try to compile and link the C++ file with:
cl 
   -I"C:\Program Files\Java\jdk1.7.0\include" 
   -I"C:\Program Files\Java\jdk1.7.0\include\win32" 
   TestJNIJessInvoke.cpp 
   -link "C:\Program Files\Java\jdk1.7.0\lib\jvm.lib"

I get a class loader exception:
Exception in thread "main" java.lang.NoClassDefFoundError: jess/Rete
        at TestJNIJessInvoke.main(TestJNIJessInvoke.java:6)
Caused by: java.lang.ClassNotFoundException: jess.Rete
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
        ... 1 more

Exception in thread "main" java.lang.NoClassDefFoundError: jess/Rete
        at TestJNIJessInvoke.main(TestJNIJessInvoke.java:6)
Caused by: java.lang.ClassNotFoundException: jess.Rete
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:423)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
        ... 1 more

Questions

1) Is there some other directory that I am supposed to be including that has the .class files for Jess? Right now all I am including is jess.jar
2) Is the general design I have a good idea? or is there a better way to facilitate communication between Jess and C++?



Thanks,
Hunter McMillen





--
V/R
-Socrates Frangis
-Mathematician & Software Engineer