It is currently Tue Sep 29, 2020 9:17 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 7 posts ] 
Author Message
 Post subject: problem calling a PB-DLL from Java
PostPosted: Thu Dec 04, 2003 6:01 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Fri Apr 25, 2003 5:22 pm
Posts: 423
Hi there,
I'm playing around with Java and DLLs. Therefore I created a DLL with PB with the following content:
Code:
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:
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:
Quote:
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


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Dec 04, 2003 9:41 am 
Offline
Enthusiast
Enthusiast

Joined: Fri Apr 25, 2003 3:56 pm
Posts: 715
Maybe you should call the dll with 4 arguments from java, as you've made the PB dll procedure take 4 args?


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Dec 04, 2003 10:01 am 
Offline
Administrator
Administrator

Joined: Fri May 17, 2002 4:39 pm
Posts: 14090
Location: France
I have an example for real JNI at home. I will package it and post it here.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Dec 04, 2003 10:24 am 
Offline
User
User

Joined: Sat Nov 08, 2003 10:29 am
Posts: 60
Location: Austria
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.


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Dec 04, 2003 11:26 am 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Fri Apr 25, 2003 5:22 pm
Posts: 423
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


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Dec 04, 2003 12:14 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Fri Apr 25, 2003 5:22 pm
Posts: 423
:?: + :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:
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:
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


Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: Thu Dec 04, 2003 2:27 pm 
Offline
Enthusiast
Enthusiast
User avatar

Joined: Fri Apr 25, 2003 5:22 pm
Posts: 423
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:
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:
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:
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


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 7 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 26 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye