Java AI Interface for Spring - Page 3

Java AI Interface for Spring

Here is where ideas can be collected for the skirmish AI in development

Moderators: hoijui, Moderators

User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Post by hoijui »

..in the meantime...
there are two issues i have that might have an impact on this.
1. the swig generated wrap code tries to redeclare long, and i get a compile error.
when i remove the following lines from JAI_wrap.cxx,

Code: Select all

/* Fix for jlong on some versions of gcc on Windows */
#if defined(__GNUC__) && !defined(__INTELC__)
  typedef long long __int64;
#endif
it compiles fine.
2. [Edit: solved!, look at end of message] i am linking against jvm.dll (there is also a jvm.lib; i dont know hte difference, but i think it should be jvm.dll).
i use the latest stable release of the JDK (1.6.0_03) on windows (test system) and on linux (build system).
i mounted the jdk directory of the windows machine on my linux machine.
..so i link against the windows jvm with -ljvm.
in the code, i have to include jni.h, which includes jni_md.h, which is OS dependent. the dir structure is as folows:
jdk/include/jni.h
jdk/include/<os>/jni_md.h
(<os> is linux on linux, and win32 on the windows jdk)

when i use -I..../jdk/include/win32, i later get an error when linking:

Code: Select all

undefined reference to `__imp__JNI_GetCreatedJavaVMs@12'
undefined reference to `__imp__JNI_CreateJavaVM@12'
collect2: ld returned 1 exit status
when i use -I..../jdk/include/linux, compiling and linking works just fine.

linux/jni_md.h

Code: Select all

#ifndef _JAVASOFT_JNI_MD_H_
#define _JAVASOFT_JNI_MD_H_

#define JNIEXPORT 
#define JNIIMPORT
#define JNICALL

typedef int jint;
#ifdef _LP64 /* 64-bit Solaris */
typedef long jlong;
#else
typedef long long jlong;
#endif

typedef signed char jbyte;

#endif /* !_JAVASOFT_JNI_MD_H_ */
win32/jni_md.h

Code: Select all

#ifndef _JAVASOFT_JNI_MD_H_
#define _JAVASOFT_JNI_MD_H_

#define JNIEXPORT __declspec(dllexport)
#define JNIIMPORT __declspec(dllimport)
#define JNICALL __stdcall

typedef long jint;
typedef __int64 jlong;
typedef signed char jbyte;

#endif /* !_JAVASOFT_JNI_MD_H_ */
both these things are about long, and .. shouldn't have to do with floating point stuff, but its the closest i could find. ;-)

2nd issue solved:
instead of -ljvm i just appended ...../jdk/lib/jvm.lib at the end of the linking command, and it linked successfully.
thought the FPUCW issue remains.
Kloot
Spring Developer
Posts: 1867
Joined: 08 Oct 2006, 16:58

Post by Kloot »

Regarding #1, Spring does not use longs*
(or long longs), as their sizes are platform-
dependant. Removing the typedef shouldn't
have any ill effects.

*e: actually, there are a few in the UDP code
and other places, but no __int64's.
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Post by hoijui »

thanks Kloot :-)

something not that important right now but...
if it all works once, how would i integrate it into the global spring compile. i mean that thing with scons, which builds spring.exe and all the AIs automatically. it somehow tries to build JAI too, when i have the folder under AI/Global, but i don't know how... does it just look for all the *.c* and *.h* files? or for makefiles?
imbaczek
Posts: 3629
Joined: 22 Aug 2006, 16:19

Post by imbaczek »

you'll need to look around rts\build\scons\ dir.
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Post by Tobi »

hoijui wrote:something not that important right now but...
if it all works once, how would i integrate it into the global spring compile. i mean that thing with scons, which builds spring.exe and all the AIs automatically. it somehow tries to build JAI too, when i have the folder under AI/Global, but i don't know how... does it just look for all the *.c* and *.h* files? or for makefiles?
In AI/Global it considers every subdirectory an AI (unless explicitly excluded in SConstruct).

In every AI it just compiles all *.c and *.cpp files (in subdirectories of the AI directory too).
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Post by hoijui »

..ahh.. and why can't it find my .h files?
do they have to be in the root of my ai folder?
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Post by Tobi »

I suppose it only adds AI/Global/JAI as include path to the compiler so you'd need to put the relative path to them from there in the #include directives.
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Post by hoijui »

id doesn't even do that, i had to use the relative path to the .h file in the include statement (relative to the file including the .h file).
now i have to find out how i'll get it to use/find jvm.lib, guess i'll put it into mingwlibs/lib.
but am finished for today, will go on tomorrow.
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Post by hoijui »

trying to get it to use jvm.lib still...

i guess i have to put jvm.lib somewhere under mingwlibs, and then specify something in rts/build/scons/config.py

Code: Select all

def CheckHeadersAndLibraries(env, conf)
is that right?

when linking in my makefile, i use jvm.lib like this (shortened):

Code: Select all

CC -o JAI.dll abc.o dce.o jvm.lib
which works.
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Zwischenbericht (von der Front) / intermediate(?) report

Post by hoijui »

a short report to let you know where i am.

1. i still get the FPUCW sync error.

what i am trying to do:
compile a small stub-dll with a class implementing IGlobalAI which forwards all calls to Java through the JNI Invocation API.
so the calls get forwarded to a java class called JGlobalAI.
this class will call back to native code, to request unit information for example through JNI.
to release me of writing lots of wrapper classes, i use swig to generate the C++ to Java code, and also for the Java to C++ code.
SWIG is meant to be used like this:
script language(Java) calls native library(C++) native code then possibly calls back to the scripting language.
what i am trying to do here, is the opposite way: native code invokes JVM and calls java methods; java methods possibly call back to native code.

so what i have to do is create a JVM by hand (writing JNI code myself to create it), then create a java class and register it with the C++ stub created by swig.
the problem now is, that the Java class can not find the native code.
i assumed that my C++ JNI exported methods are available in Java when i create the JVM from this very dll, but it somehow seems not to be the case. it neither works when i explicitly load my JAI.dll from the java code.

if i understood it correctly, the same problem occurred in the C# AI interface. where the C# code had to call the C++ code, and it didnt work the other way around.
possibly i will end up doing the same.
who did the C# interface again? :/
how did you do it?

i will try to write a minimal test scenario, where i start a JVM from native code, call a Java method, and let java call back into native code.

has anyone done something like that already?
User avatar
DJ
Posts: 355
Joined: 17 Jan 2007, 13:26

Post by DJ »

Hugh Perkins did the C# interface, send him a PM and he might be able to help you.
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Post by hoijui »

thanks DJ :-)
i wrote the small test scenario, and it really seems nto to be possible the way i wanted.
i create a JVM from native code, call a java method from native code (works fine till here), and then let that java method call a native method, which fials with an UnsatisfiedLinkError
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Post by hoijui »

... it does work!

what is needed is a

Code: Select all

System.loadLibrary("LibraryName");
in the Java File.
though i did this in JAI too, it didn't work there... maybe i did something wrong again there. looking into that again now.
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Post by hoijui »

i was/am doing a loadLibrary("JAI") in java, and it successfully loads the library, but i still get the UnsatisfiedLinkError.
i checked with an utility, and JAI.dll is exporting the method that java requests (swig_module_init).
i also looked into the FPUCW sync thing again, but neither got further there.
whole day for nothing -> starts to suck ;-)

this project would need a native expert, not someone like me who knows the java world only, though such a person doesn´t need a java interface ...
i looked at JVM arguments, but there is nothing to change the precision control of the FPU.

i hope someone of you gets an idea once, so i can go on, i won't try it myself anymore, making me to pissed off (spending nearly 2 weeks already, just fiddling around with compile arguments, linking stuff, swig parameters and instructions)
User avatar
AF
AI Developer
Posts: 20687
Joined: 14 Sep 2004, 11:32

Post by AF »

System.loadbirary attempts to load a native library using JNI.

You cant just make ordinary API calls using JNI you have to write JNI functions in the C++ specifically for JNI using a certain format and taking java defined variable types. Pass an IGlobalAI* and it'll come out as an integer on the java end.

This is why your getting unsatisfied link errors.

declare a java class filled with methods flagged as native and then run javah on the class file to get a set of C function declarations. Fill in the variable names of the parameters and add implementations. Then you'll hava a java -> C/C++ JNI setup.

imo using swig is not the best idea. Its not hard or complicated to use JNI, it just requires a little reading to get through it.

Creating a java vm and using similar mechanisms to spawn a jobject variable of type "MyJavaAI" then passing constructed objects to pre-specified methods shouldnt be hard.

As for fpu, the java VM does indeed mess with the fpu registers. Java floating point numbers work at 64bit precision regardless of the operating system, e.g. linux at 80bit precision. If it didnt do that then java programming would have a lot of holes in its calculations.
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Post by hoijui »

well... thanks AF, but i knew all this ;-)
i used JNI before (in both ways, Java->native and native->Java), i know how it works.
as SWIG is just generating code that uses JNI, it is the same like writing JNI by hand.
swig creates a Java class with native functions, then generates a header file for it, and then provides the implementations ina a .cxx file, -> the same one would do by hand.
i just though it would be nice to not have to change the JAI code when the Spring code changes, but instead just run swig.
i dont know if it were that simple to do by hand. thinking on object lifetime management and references of Native objects stored in the Java side or vise versa.
but yeah...
if it wont work with SWIG, one still could use the SWIG generated stuff as a base, and modify it by hand till it works.
the 2 main problems there are right now dont have to do with JNI and FPU, nothing with SWIG as i see it.
i possibly would be able ot solve the problem with JNI somehow, but most likely not the FPU thing.
so at least till someone can help me there, i'll pause the project.
,,tough if you want to go on... i'll send you the latest version of what i have if you want, or just start from scratch.
User avatar
Agon
Posts: 527
Joined: 16 May 2007, 18:33

Post by Agon »

Good to see, that a new language for the AI is in developing.
But I don't really like Java :| .

Why, not making a mono interface with java inside?
You would support more than one language.

http://www.mono-project.com/Java
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

pause

Post by hoijui »

i just had a short chat with tobi in the lobby, and he helped me solve a problem i had (yes, i begann working on JAI agian). this time i tryed to do it by hand, as described by AF above. it should theoretically not make a difference, but well...
with the help of tobe and streflop, i got ridd of the sync error messages as follows:
each method call from C/C++ to java gets sourounded like this:

Code: Select all

streflop_init<streflop::Double>();
jniEnv->CallVoidMethod(javaAiInst, method_id);
streflop_init<streflop::Simple>();
i guess the init after the method call would be enough for its own, as java will set the FPU as it wants it anyway. what do you think, should i leave it like this or remove the streflop_init<streflop::Double>(); ?

beside this, i am using JNA at the moment for calling back into C from Java. this also works already. so.. all main technical problems seem to be solved (for the moment). i also wrote the wrappers for all the methods in the GlobalAICallback and AICheat callback already, but i also need java wrappers for all the structs like UnitDef, Command and so on. After that, i guess i will be having some pointer issues (some beeing removed to early, some too late or so). and then some cleanup... and it may be usable.
the problem is: this is my last day here, tomorow early morning i'll leave for half a year, in which i wont have access to a computer regularly. so i will go on when i come, in the beginning of july.

about mono:
i said it in a private message to Agon already:
i am not interested in mono, and when workign with Java and C, i at least have a good idea of one of the parts, which is annoying and frustrating enough already (cause i dont feel at home in the C world, with all the flags and defines and such) ;-)

so maybe in the version that comes after 0.76 we'll see JAI available ;-)
i hope so!
Tobi
Spring Developer
Posts: 4598
Joined: 01 Jun 2005, 11:36

Re: Java AI Interface for Spring

Post by Tobi »

I think you can indeed leave away the streflop call before the java method.

Sorry I didn't take a look at the code myself btw, really didn't have time for it between all other things, but I should have at least said that I guess..
McLoud
Posts: 36
Joined: 03 Sep 2006, 22:31

Re:

Post by McLoud »

Agon wrote:Good to see, that a new language for the Why, not making a mono interface with java inside?
Because is hard to build the native <-> CLR bridge. Good luck with that.
Agon wrote:Good to see, that a new language for the You would support more than one language.
The JVM supports more than 200 languages. Java is just the first class citizen.
Post Reply

Return to “AI”