News:

Building a 3D Ray Tracer  By stevmjon

Main Menu

LinkDLL query

Started by hatonastick, August 24, 2006, 02:51:18 PM

Previous topic - Next topic

hatonastick

I'm currently trying to access a DLL I wrote in C which handles extremely raw TCP/IP streams.  Anyway I thought I'd start by just seeing if I could get the DLL version number (not really a useful function, more for testing the DLL like we are here) but I kept getting the following error: Linked DLL function does not exist. -> print str$(HNVersion())

Here's the PB code (so far):

PlayBASIC Code: [Select]
; Check to see if our DLL exists first.
if fileexist("HatNet.dll")=true
; Bind our DLL commands to make a useable PB TCPIP command set
linkDLL "HatNet.dll"
; HatNet version number
HNVersion() alias "Version" as integer
endlinkdll
else
print "DLL not found!"
sync
waitkey
end
endif

print str$(HNVersion())

Sync
WaitKey



Now LinkDLL doesn't appear to allow you to set the calling convention, so what does it default to?  I can change this easily in my DLL if I have to.  I'd prefer to use LinkDLL to the other system of calling DLL's in PB if I can.
Matthew 5:14-16

hatonastick

#1
Um nevermind.  I found the problem.  I'd forgotten to set a particular option while compiling my DLL. :-/

[Edit]
Ok what I would like clarified:
1) Using LinkDLL can I pass a "pointer" to a block of memory (ie. a memory bank) to a function in the DLL? (along the lines of what Kevin described to Adaz)  If so, how do I do this?  (actually I suspect I might know how to - will try and see what happens :)) Or do I have to use the other method of communicating with DLLs?  I need to know this to work out which method I should be using.
2) Is LinkDLL _stdcall convention only?  This isn't so important - more just curious. :)
Matthew 5:14-16

kevin

#2
  It defaults to standard.  Your right, ATM  there's no way of setting the call conversion, which is admittedly an oversight, plus functions can only accept 32bit Integer/32bit Floats and String param's.  So anything outside of the requires a wrapper.

The example above really should be this.
PlayBASIC Code: [Select]
; Bind our DLL commands to make a useable PB TCPIP command set
linkDLL "HatNet.dll"
; HatNet version number
HNVersion() alias "Version" as integer
endlinkdll

; Check to see if our DLL exists first.
if fileexist("HatNet.dll")=true
print "DLL not found!"
sync
waitkey
end
endif

print HNVersion()

Sync
WaitKey



hatonastick

Thanks for that.  I can see it's going to take me a long time to get my head around the right way to do things in PB. :)
Matthew 5:14-16

hatonastick

Erm I meant as a "dyed-in-the-wool" C language kludger.  I wasn't insinuating there is anything wrong with PB!  :)
Matthew 5:14-16

kevin


If there's wasn't anything wrong with PB we'd be finnished..  Oh what a day that will be.


So what do you want to pass out ?

hatonastick

Ha, good programming projects are never finished - they just go on and on until their authors are.  Or in my case, until I'm distracted by something else.  Ooo look, shiny thing!  :)

Eh?  In my DLL?  I think I wanted to pass a pointer to a memory bank in PB to my TCP/IP DLL.  I ended up using your work-around which seems to work fine.  Hopefully nothing too nasty happening behind the scenes. :)

If that's not what you are asking, don't mind me I think my brains fried.  Sorry I probably should have edited my other post instead of making another reply - that way it would have been corrected without showing up as if I was still asking questions on this subject.  I think.
Matthew 5:14-16

kevin

  In order to safely allocate memory Banks or Arrays are the preferred way.  You might find using the  GeyArrayPtr() function easier come to think of it, just don't write into the header, you'll break it  :)

As then the user can pass an array of sorts to the query function, then on return, simply get the results from array in PB code, rather than peeking the values out.

hatonastick

Hmm could you give me a simple (and it doesn't even need to be compilable) illustration of using arrays in this way?  Essentially how do I avoid writing to the array header?
Matthew 5:14-16

kevin

#9
 Here's the tidbit from the projects/example/Arrays.  


Updated Version:

PlayBASIC Code: [Select]
; Create an Array Called Table()
Dim Table(10)
For lp=0 to 10
Table(lp)=100+lp
Next

; Get the Address of the first data cell in this array
Address=GetArrayPtr(table(),true)

; peek the array memory and show the elements
ShowArray(Address)

; manually poke some new values into this arrays memory
print "Poking Data Directly Into This Arrays Memory"
For lp=0 to 10
PokeInt address+(lp*4),2000+lp
next

;show the array memory again
ShowArray(Address)

sync
waitkey



Function ShowArray(Address)
print "Display Array Data"
For lp=0 to 10
print PeekINt(Address+(lp*4))
next
EndFunction







Original code for very old Versions of PlayBASIC:

PlayBASIC Code: [Select]
 Constant PBArray_DataOffset=92

; Create an Array Called Table()
Dim Table(10)
For lp=0 to 10
Table(lp)=100+lp
Next

; Get the Addres of this array
Address=GetArrayPtr(table())

; peek the array memory and show the elements
ShowArray(Address)

; manually poke some new values into this arrays memory
print "Poking Data Directly Into This Arrays Memory"
DataAddress=Address+PBArray_DataOffset
For lp=0 to 10
PokeInt Dataaddress+(lp*4),2000+lp
next

;show the array memory again
ShowArray(Address)

sync
waitkey



Function ShowArray(Address)
print "Display Array Data"
DataAddress=Address+PBArray_DataOffset
For lp=0 to 10
print PeekINt(Dataaddress+(lp*4))
next
EndFunction





hatonastick

Thanks for that - will have to give it a go. :)  Will the ability to pass pointers of memory banks to DLLs be added in the future to PB?  Just curious.
Matthew 5:14-16

kevin


You can already pass them as integers