problem calling a PB-DLL from Java

Just starting out? Need help? Post your questions and find answers here.
Froggerprogger
Enthusiast
Enthusiast
Posts: 423
Joined: Fri Apr 25, 2003 5:22 pm
Contact:

problem calling a PB-DLL from Java

Post by Froggerprogger »

Hi there,
I'm playing around with Java and DLLs. Therefore I created a DLL with PB with the following content:

Code: Select all

ProcedureDLL.l testfunction(a.l, b.l, c.l, d.l)
  MessageRequester("",Str(a)+"   "+Str(b)+"   "+Str(c)+"   "+Str(d),0)
  ProcedureReturn 1
EndProcedure
Then I tried to call this function from Java using the following code:

Code: Select all

class dllCallClass 
{
	public static native int testfunction (int c, int d);

	static
  	{
	  	System.loadLibrary("testdll");
  	}
}

class testprog
{
	public static void main(String [] parm)
    {
		dllCallClass t = new dllCallClass();

   		t.testfunction(66,77);
   	}
}
But when I run it I get the errormessage:
Exception in thread "main" java.lang.UnsatisfiedLinkError: testfunction
at dllCallClass.testfunction(Native Method)
at testdll.main(testdll.java:19)
It seems that Java doesn't find the correct entry-point of this function. But it finds and opens the DLL (otherwise there would be another message).
Do you have an idea ? Perhaps I have to manipulate/convert the DLL ?

Huh, it's 6 o'clock in the morning, I should go to bed...
%1>>1+1*1/1-1!1|1&1<<$1=1
Pupil
Enthusiast
Enthusiast
Posts: 715
Joined: Fri Apr 25, 2003 3:56 pm

Post by Pupil »

Maybe you should call the dll with 4 arguments from java, as you've made the PB dll procedure take 4 args?
Fred
Administrator
Administrator
Posts: 16681
Joined: Fri May 17, 2002 4:39 pm
Location: France
Contact:

Post by Fred »

I have an example for real JNI at home. I will package it and post it here.
javabean
User
User
Posts: 60
Joined: Sat Nov 08, 2003 10:29 am
Location: Austria

Post by javabean »

I haven't worked with native code in JAVA so far!
But it seems that you have to write a C/C++ wrapper-dll to access the PB-dll.
Just search the Java-Forums at http://forum.java.sun.com

For example I found the following threads:
http://forum.java.sun.com/thread.jsp?fo ... ead=184460
http://forum.java.sun.com/thread.jsp?fo ... ead=424201
http://forum.java.sun.com/thread.jsp?fo ... ead=411926
http://forum.java.sun.com/thread.jsp?fo ... ead=408930

and here is a tutorial on how to use JNI:
http://java.sun.com/docs/books/tutorial ... stepbystep

It would be nice to see your post here again if you succeed in accessing the PB-dll.
Froggerprogger
Enthusiast
Enthusiast
Posts: 423
Joined: Fri Apr 25, 2003 5:22 pm
Contact:

Post by Froggerprogger »

Thank you all for your answers!

@pupil: The first to arguments must not be called, they are used internally by the JNI to communicate with the function. But it looks strange for sure!

@javabean: I googled around a lot in the last hours but I found nowhere a hint for simple DLL-access like OpenLibrary(). It seems that there's really no alternative to a C/C++-Wrapper-DLL. The problem is, I have never done anything with C/C++ in my life, so it would be a hard hack for me, and it would be not as 'Pure' as patching it with PB-facilities.

@Fred: Is it the C/C++-hack or another way? It would be pretty cool if you found a way to do it more simple. :P
%1>>1+1*1/1-1!1|1&1<<$1=1
Froggerprogger
Enthusiast
Enthusiast
Posts: 423
Joined: Fri Apr 25, 2003 5:22 pm
Contact:

Post by Froggerprogger »

:?: + :idea: => :P :P :P

Yeah, I got it!
It's just as easy as... don't know

Here's the 'trick':
All you have to do is to rename your PB-Procedures.
If your Java-program calls the function 'testfunction', then your PB-procedure has to have the name 'Java_ClassNameOfCallingClass_testfunction'
That's all.
It's not soo convenient, because you have to rename your PB's procedures always if they should be called from another Java-program's class, but anyway, it works.
I tried it with byte (byte), word (short), long (int) and float (float).
I think a workaround for doubles would work, too.
But I wasn't able to send/receive a String, not even converted to a byte[]-array in Java. hmmm. It seems, that there's really a big difference in their handling, or it's not possible to access the other program's memory or something like that - I will try a little bit more.

But first, here's an example:

The PB-DLL:

Code: Select all

ProcedureDLL.b Java_dllCallClass_testfunctionB(a.l, b.l, c.b, d.b)
  MessageRequester("",Str(a)+"   "+Str(b)+"   "+Str(c)+"   "+Str(d),0)
  ProcedureReturn c + d
EndProcedure

ProcedureDLL.w Java_dllCallClass_testfunctionW(a.l, b.l, c.w, d.w)
  MessageRequester("",Str(a)+"   "+Str(b)+"   "+Str(c)+"   "+Str(d),0)
  ProcedureReturn c + d
EndProcedure

ProcedureDLL.l Java_dllCallClass_testfunctionL(a.l, b.l, c.l, d.l)
  MessageRequester("",Str(a)+"   "+Str(b)+"   "+Str(c)+"   "+Str(d),0)
  ProcedureReturn c + d
EndProcedure

ProcedureDLL.f Java_dllCallClass_testfunctionF(a.l, b.l, c.f, d.f)
  MessageRequester("",Str(a)+"   "+Str(b)+"   "+StrF(c)+"   "+StrF(d),0)
  ProcedureReturn c + d
EndProcedure
And the Java-Code:

Code: Select all

class dllCallClass 
{
	public static native byte testfunctionB (byte c, byte d);
	
	public static native short testfunctionW (short c, short d);
	
	public static native int testfunctionL (int c, int d);
	
	public static native float testfunctionF (float c, float d);
	
	static
  	{
	  	System.loadLibrary("testdll");
  	}
}



class starttestdll
{
	public static void main(String [] parm)
    {
		dllCallClass t = new dllCallClass();
		
		System.out.println(t.testfunctionB((byte) 12,(byte) -23));

		System.out.println(t.testfunctionW((short)1234,(short)-2345));

		System.out.println(t.testfunctionL(23456,-34567));
		
		System.out.println(t.testfunctionF((float) 2.345,(float) -3.456));
		
   	}
}
Just compile the DLL and copy it to the directory of the Java-file. :P

OK, now I will have a deeper look at the other types (strings, pointer, structures, arrays, lists), there is written something about it somewhere in the Net...

edit: now it's 12:17 - hmmm - i forgot to sleep last night !!! not 1 minute !!! It was just getting dark and then bright again...
%1>>1+1*1/1-1!1|1&1<<$1=1
Froggerprogger
Enthusiast
Enthusiast
Posts: 423
Joined: Fri Apr 25, 2003 5:22 pm
Contact:

Post by Froggerprogger »

Hmmmm. I tried now to use strings, but all I reached is a workaround-hack.
I read the C-Header-files coming along with the SDK and these documents:
http://java.sun.com/docs/books/tutorial ... tring.html
It seems that using Strings/Arrays/etc. is really a big problem that could only be solved using Instances, or something like this, because Strings and the other stuff are objects including some methods and pointer to pointer to data, etc. I have really NO knowledge about how to implement it.
All I reached during 'controlled peeking around' was to send Strings from Java to PB. Java sends the DLL a pointer, and when you look at

Code: Select all

PeekL(PeekL(PeekL(*str)+8)+8)
you'll find the information on the string-length followed by a 16-Bit-String.
So you can read the String with:

Code: Select all

For i=0 To strLen - 1
    str$ + Chr(PeekL(PeekL(PeekL(*str)+8)+12+2*i))
  Next
This works fine for now, but will not work with other Stringformats and it is not the fine way. And, it's not possible for me to create a new String-object in such a manner to send back to Java.
Hmmm. Does anybody perhaps have an idea how to implement the object-types Array, String, etc. :?:

edit:
Here's a snippet how to get the String:

Code: Select all

ProcedureDLL.s GetJavaString(*str.l)
  Protected str$.s
  Protected strLen.l
  
  strLen = PeekL(PeekL(PeekL(*str)+8)+8)
  
  For i=0 To strLen - 1
    str$ + Chr(PeekL(PeekL(PeekL(*str)+8)+12+2*i))
  Next

  ProcedureReturn str$
EndProcedure

ProcedureDLL.l Java_dllCallClass_testfunctionS(a.l, b.l, c.l, d.l)
  str1$ = GetJavaString(c)
  str2$ = GetJavaString(d)
  
  MessageRequester("","length: "+Str(Len(str1$))+Chr(13)+Chr(10)+"text:  "+"   "+str1$,0)
  MessageRequester("","length: "+Str(Len(str2$))+Chr(13)+Chr(10)+"text:  "+"   "+str2$,0)
   
  ProcedureReturn 1
EndProcedure
Just implement with e.g. testfunctionS(String c, String d);
%1>>1+1*1/1-1!1|1&1<<$1=1
Post Reply