Java Unitsync

Java Unitsync

Discuss the source code and development of Spring Engine in general from a technical point of view. Patches go here too.

Moderator: Moderators

Post Reply
User avatar
Petah
Posts: 426
Joined: 13 Jan 2008, 19:40

Java Unitsync

Post by Petah »

Has any one got an up to date binding of the unitsync library for java?
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Re: Java Unitsync

Post by hoijui »

the java bindings are deprecated, you should just use JNA.
a tip: use JNAErator to generate the Java stuff to interface to unitsync through JNA:
http://code.google.com/p/jnaerator/
User avatar
Petah
Posts: 426
Joined: 13 Jan 2008, 19:40

Re: Java Unitsync

Post by Petah »

Sorry let me rephrase, has anyone got a working Java UnitSync class that uses JNA?

If not Ill look into generating one myself.

Also I tried using something else you posted hoi, unitsyncJNAWrapp.zip, it was ages ago though. It worked except I get errors on some functions like

Code: Select all

public byte[] GetMinimap(String filename, int miplevel);
Exception in thread "main" java.lang.IllegalArgumentException: Unsupported return type class [B in function GetMinimap
http://springrts.com/phpbb/viewtopic.ph ... nc&start=0
User avatar
Petah
Posts: 426
Joined: 13 Jan 2008, 19:40

Re: Java Unitsync

Post by Petah »

I used JNAerator to generate a file. It worked but certain functions like GetMinimap return an int. I presume this int is some kind of pointer but how do i access the data?

The code is @ http://pastebin.com/f5c9df95f because these forums think im attacking them by attaching the file.
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Re: Java Unitsync

Post by hoijui »

try replacing the "int" with "byte[]" in the generated java file. I guess you were right with the int beeing a pointer, but JNA supports array mapping (see their page for more info, they support really a lot). maybe there is even a JNAerator option to do this automatically.
User avatar
Petah
Posts: 426
Joined: 13 Jan 2008, 19:40

Re: Java Unitsync

Post by Petah »

when changing it to byte[] i just get an error

Code: Select all

java.lang.ExceptionInInitializerError
Caused by: java.lang.NullPointerException
        at java.lang.reflect.Array.getLength(Native Method)
        at com.sun.jna.Structure$FFIType.<init>(Structure.java:1194)
        at com.sun.jna.Structure$FFIType.get(Structure.java:1245)
        at com.sun.jna.Structure$FFIType.get(Structure.java:1212)
        at com.sun.jna.Native.register(Native.java:1249)
        at com.sun.jna.Native.register(Native.java:1003)
        at org.petah.spring.UnitSync2.<clinit>(UnitSync2.java:24)
Could not find the main class: org.petah.spring.UnitSync2.  Program will exit.
Exception in thread "main" Java Result: 1
User avatar
AF
AI Developer
Posts: 20687
Joined: 14 Sep 2004, 11:32

Re: Java Unitsync

Post by AF »

The getminimap callout in itself is a horrid callout in my opinion and needs replacing with somethign a little more friendly. Other API bindings could simply pass a filepath instead and have it output a jpeg for them, why cant we do the same here without faffing around if we're using anything that doesnt compile natively into x86?
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Re: Java Unitsync

Post by hoijui »

for anyone possibly interested. the solution was to remove all occurences of the EXPORT macro from the native source file before feeding it into JNAerator.
User avatar
Petah
Posts: 426
Joined: 13 Jan 2008, 19:40

Re: Java Unitsync

Post by Petah »

Ive ran into a problem when calling GetMapInfo, it causes the JVM to crash probably because of an error occurring the the c code.

It seems almost random as it occurs on many different maps on different runs. However its normally within the first 5 or so maps scanned.

Here is the console output from the crash

Code: Select all

run:
LogOutput initialized.
Spring 0.80.4.0 (0.80.4-0-ga0534a8{@}-cmake-mingw32)
Available log subsystems: VFS-detail, VFS, ArchiveScanner, unitsync
Enabled log subsystems: unitsync
Enable or disable log subsystems using the LogSubsystems configuration key
  or the SPRING_LOG_SUBSYSTEMS environment variable (both comma separated).
unitsync: loaded, 0.80.4.0 (0.80.4-0-ga0534a8{@}-cmake-mingw32)
default config file: C:\Users\Petah\AppData\Local\springsettings.cfg
Using read-write data directory: D:\Games\Spring\
Using read-only  data directory: C:\Users\Petah\Documents\My Games\Spring\
Using read-only  data directory: C:\Users\Petah\Documents\Spring\
Using read-only  data directory: C:\ProgramData\Spring\
Scanning: C:\ProgramData\Spring\maps
Scanning: C:\ProgramData\Spring\base
Scanning: C:\ProgramData\Spring\mods
Scanning: C:\ProgramData\Spring\packages
Scanning: C:\Users\Petah\Documents\Spring\maps
Scanning: C:\Users\Petah\Documents\Spring\base
Scanning: C:\Users\Petah\Documents\Spring\mods
Scanning: C:\Users\Petah\Documents\Spring\packages
Scanning: C:\Users\Petah\Documents\My Games\Spring\maps
Scanning: C:\Users\Petah\Documents\My Games\Spring\base
Scanning: C:\Users\Petah\Documents\My Games\Spring\mods
Scanning: C:\Users\Petah\Documents\My Games\Spring\packages
Scanning: D:\Games\Spring\maps
Error opening D:\Games\Spring\maps\AATA-RumblingForest.sd7: Unknown error
Error opening D:\Games\Spring\maps\Foothills-v07.sdz
Error opening D:\Games\Spring\maps\High_and_Low_Redux.sd7: Unknown error
Error opening D:\Games\Spring\maps\Relics-V2.sd7: Unknown error
Scanning: D:\Games\Spring\base
Scanning: D:\Games\Spring\mods
Scanning: D:\Games\Spring\packages
unitsync: initialized, 0.80.4.0 (0.80.4-0-ga0534a8{@}-cmake-mingw32)
unitsync: joining
275
------------------------------------------
1944_BocageSmall.smf
-1870956879
unitsync: get map info: 1944_BocageSmall.smf
unitsync:   startpos: 600, 600
unitsync:   startpos: 3600, 3600
unitsync:   startpos: 3600, 600
unitsync:   startpos: 600, 3600
unitsync:   startpos: 2000, 600
unitsync:   startpos: 2000, 3600
#
# An unexpected error has been detected by Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x76e8814c, pid=3372, tid=8484
#
# Java VM: Java HotSpot(TM) Client VM (11.3-b02 mixed mode, sharing windows-x86)
# Problematic frame:
# C  [ntdll.dll+0x6814c]
#
# An error report file with more information is saved as:
# D:\Games\Spring\hs_err_pid3372.log
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
Java Result: 1
BUILD SUCCESSFUL (total time: 7 seconds)
The source for the UnitSync class and NativeUnitSync class is here
http://pastebin.com/fa727c1e and http://pastebin.com/m39e833c6

The JVM error log file is here http://pastebin.com/f354de4ce
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Re: Java Unitsync

Post by hoijui »

The best guess i have is that this comes from you not using the StdCalling convention.

i am new to this too, but my guess is, the problem lies in the first few lines in the NativeUnitSync class. You are using DEFAULT_OPTIONS, but i think you will have to manually specify StdCalling convention there, somehow. Also, when you call the Native.register() method, i think you should pass it the above created NativeLibrary instance, and not the name.

I am working on a nearly equal issue with the Java AI Interface callback ;-) so maybe we can help each other when doing progress.
User avatar
hoijui
Former Engine Dev
Posts: 4344
Joined: 22 Sep 2007, 09:51

Re: Java Unitsync

Post by hoijui »

the way i am doing it now:

Code: Select all


	static {
		java.util.Map<String, Integer> myNativeLibOptions = new java.util.HashMap<String, Integer>();
		if (isWin32()) {
			myNativeLibOptions.put(Library.OPTION_CALLING_CONVENTION, com.sun.jna.win32.StdCallLibrary.STDCALL_CONVENTION);
		}
		NativeLibrary myNativeLib = NativeLibrary.getInstance("AIInterface", myNativeLibOptions);
		Native.register(myNativeLib);
	}

	public static final boolean isWin32() {

		final String osName     = System.getProperty("os.name", "UNKNOWN");
		final boolean isWindows = osName.matches("[Ww]in");
		final String arch       = System.getProperty("sun.arch.data.model", "32");
		final boolean is32bit   = arch.equals("32");
		//final String arch       = System.getProperty("os.arch", "foobar");
		//final boolean is32bit   = arch.equals("x86");
		return (isWindows && is32bit);
	}
compiles and runs, though as i strangely had no problems before...
apart of the ugly way to find out that we are running win32, this seems like the right way to go.
cranphin
Posts: 136
Joined: 13 Jun 2005, 16:37

Re: Java Unitsync

Post by cranphin »

In case anyone is still interested, and hasn't figured it out yet :)

The reason for GetMapInfo to crash is that the passed MapInfo object has two string fields, which need to be filled already :)

So:

Code: Select all

        public String description= new String(new char[255+1]); // /< Description (max 255 chars) 
These two classes work for me :)

Code: Select all

    public static class StartPos  extends Structure {
        public int x; ///< X component // 4
        public int z; ///< Z component // 4
        
    }
    
    public static class MapInfo extends Structure {
        public String description= new String(new char[255+1]); // /< Description (max 255 chars) //4
        public int tidalStrength; // /< Tidal strength //4 - 8
        public int gravity; // /< Gravity // 4 - 12
        public float maxMetal; // /< Metal scale factor // 4 - 16
        public int extractorRadius; // /< Extractor radius (of metal extractors) // 4 - 20
        public int minWind; // /< Minimum wind speed // 4 - 24
        public int maxWind; // /< Maximum wind speed // 4 - 28

        // 0.61b1+
        public int width; // /< Width of the map // 4 - 32
        public int height; // /< Height of the map // 4 - 36
        public int posCount; // /< Number of defined start positions // 4 - 40
        public StartPos[] positions = (StartPos[]) new StartPos().toArray(16); // 2 * 4 * 16 = 128 0 168
        // new StartPos.ByValue[16]; ///< Start positions defined by the map (max 16)

        // VERSION>=1
        public String author = new String(new char[200+1]); // /< Creator of the map (max 200 chars) // 4 - 172

    }
User avatar
AF
AI Developer
Posts: 20687
Joined: 14 Sep 2004, 11:32

Re: Java Unitsync

Post by AF »

Would new String("") or even new String("-") be less wasteful? If only because there's less memory use, and your no longer inviting potential undefined behaviour via the creation of a new char array whose values are undefined?
cranphin
Posts: 136
Joined: 13 Jun 2005, 16:37

Re: Java Unitsync

Post by cranphin »

AF wrote:Would new String("") or even new String("-") be less wasteful? If only because there's less memory use, and your no longer inviting potential undefined behaviour via the creation of a new char array whose values are undefined?
NO! :)
The point is that the unitsync code needs a pre-allocated byte array to dump it's string in.
That's why they added those //max 200 comments. That's the length of the array that's needed to contain anything they may put in there :)
If you use a empty string, unallocated memory is gonna be written in, and you get all kinds of pain XD

Ohyeah..
In java, anything created has default values :)
creating a char[100] array means you create a char array with 100 '0' values :)
User avatar
AF
AI Developer
Posts: 20687
Joined: 14 Sep 2004, 11:32

Re: Java Unitsync

Post by AF »

But does this not then get interned by the VM? String is a special case object in java hmmm
cranphin
Posts: 136
Joined: 13 Jun 2005, 16:37

Re: Java Unitsync

Post by cranphin »

AF wrote:But does this not then get interned by the VM? String is a special case object in java hmmm
JNA makes char arrays out of the String.
JNA can't telepathically know how big those arrays need to be :)
So you use a String of a certain size, to let it know how big to make the array :)
I don't know if it uses the backing array of the String to pass, or creates a newone, I think the lastone.
So your kinda right at wasted space, tho it'll soon be garbish collected.
But there's not really many other ways, and there always needs to be an allocated array to pass to the code, of size 200 :)
User avatar
AF
AI Developer
Posts: 20687
Joined: 14 Sep 2004, 11:32

Re: Java Unitsync

Post by AF »

Ah thanks cranphin ( lols at aegis )
Post Reply

Return to “Engine”