View Full Version : Newb help with dll
MouseTrap
16-02-2009, 22:40
Hi, I just started with ThinBasic. I'm very pleased so far.
I'm hoping someone can help me with thinbasic crashing
I'm attempting to load a dll and use its functions. im sure i'm doing something wrong.
uses "CONSOLE"
randomize
'DECLARE function SetupMap LIB "C:\Dev\test1.DLL" ALIAS "SetupMap" (byref arrayhandle as long, Diag as long) as long
const _SIZE as long = 50
dim pMapArr as long
dim arr(_SIZE,_SIZE) as single at pMapArr
dim i,j as integer
for i = 1 to 50
for j = 1 to 50
arr(i,j) = rnd
print(arr(i,j), $crlf )
next
next
waitkey
Running this script causes and exception and launches the vstudio debugger.
I'm defining the array at another variable because I want to pass it as an arg to the dll for processing.
Any advice?
Thanks
ErosOlmi
16-02-2009, 22:46
Hi MouseTrap.
I suppose you are passing to your external function a pointer to the array so change from:
DECLARE function SetupMap LIB "C:\Dev\test1.DLL" ALIAS "SetupMap" (byref arrayhandle as long, Diag as long) as long
to
DECLARE function SetupMap LIB "C:\Dev\test1.DLL" ALIAS "SetupMap" (BYVAL arrayhandle as long, Diag as long) as long
because pointers must be passed BYVAL otherwise thinBasic will pass a pointer to a pointer.
Not sure about Diag if you want to pass a BYREF Diag AS LONG or a BYVAL Diag AS LONG.
Ciao
Eros
MouseTrap
16-02-2009, 22:52
Thanks for the quick reply!
Does that explain the crash of thinbasic? the declare line was commented out.
You should be able to run the script as is and duplicate the crash.
Diag is just a flag for the pathfinder to do 4-way,8-way or 8-way-cut-corner pathing.
Thanks
ErosOlmi
16-02-2009, 22:56
I was re-reading again your post (sorry I missed your question at first)
Here the solution:
uses "CONSOLE"
randomize
const _SIZE as long = 50
dim pMapArr as long
pMapArr = heap_alloc(_size * _size * sizeof(SINGLE)) '---<<<< ALLOCATE memory
dim arr(_SIZE,_SIZE) as single at pMapArr
dim i,j as integer
for i = 1 to _SIZE
for j = 1 to _SIZE
arr(i,j) = rnd
printl arr(i,j)
next
next
waitkey
DIM ... AT ... statement is a powerful statement for over imposing a logical structure to an already allocated memory.
DIM ... AT ... does not allocate any mameory but expect that memory at defined position is already allocated.
In my revised example I allocated memory by using:
pMapArr = heap_alloc(_size * _size * sizeof(SINGLE))
50 * 50 * the size of the single element.
but it can be done in many other ways or by an external function or whatever.
Hope to have replied to your question.
Ciao
Eros
ErosOlmi
16-02-2009, 23:01
If you do not have any particular reason why using DIM ... AT ... statement, just use standard DIM :
uses "CONSOLE"
randomize
const _SIZE as long = 50
dim pMapArr as long
dim arr(_SIZE,_SIZE) as single
dim i,j as integer
for i = 1 to _SIZE
for j = 1 to _SIZE
arr(i,j) = rnd
printl arr(i,j)
next
next
waitkey
Ciao
Eros
MouseTrap
16-02-2009, 23:04
Ahh. I see now.
Thank you very much!
[EDIT]
If you do not have any particular reason why using DIM ... AT ... statement, just use standard DIM :
I wasnt sure how to reference a pointer and the At keyword seemed like the trick.
I've been playing around a lot with O2h and misunderstood the allocation issue with the keyword.
ErosOlmi
16-02-2009, 23:13
O2H (I suppose you are referencing to Charles Pegge module for thinBasic (http://community.thinbasic.com/index.php?board=159.0)) among other things, compiles source code to machine code and returns a pointer to the just compiled machine code. Than DECLARE ... AT ... statement is than used used to define a script function that (when executed) jumps to that memory area, executed machine code and return. So it is like a Just In Tim compiler.
Charles is implementing it a lot. Great news are quite ready to be presented on this area.
Ciao
Eros
ErosOlmi
16-02-2009, 23:16
I wasnt sure how to reference a pointer and the At keyword seemed like the trick.
Yes, it can be used in that way.
Imagine you have an external DLL function that allocates an array of SINGLEs (like in your example).
If you have a pointer to that very first element of the array and the number of elements, you can use DIM ... AT ... to use that array even if not allocated by thinBasic script.
MouseTrap
16-02-2009, 23:28
If you have a pointer to that very first element of the array and the number of elements, you can use DIM ... AT ... to use that array even if not allocated by thinBasic script.
That's my next task after i get this first function to work, The path will be generated and an array pointer will be returned for use in TB.
What I want to happen is a function is called 'GetPath' that take a 'long' as an REF argument.
The argument is set with the length of the path and the pointer is returned from the dll.
then In TB I allocate a new array based on the length use it in the script.
I dont know if this is possible. I'm new to TB but just experimenting to get a handle on the language and runtime.
Thanks
ErosOlmi
16-02-2009, 23:34
Yes, it can be done absolutely.
If you have any problem, just post a piece of the source script and the DLL you are using and I will try to help.
Ciao
Eros
MouseTrap
17-02-2009, 01:42
[EDIT]
I got it working. I was returning it seems the wrong kind of pointer from the dll.
Thanks much for your help! I'll post an example later.
I've got it *almost working.
The final issue is accessing the array returned by the dll function. Right now instead of giving me a grid coord, its returning some kind of pointer.
Everything is working until last line where the array is accessed.
uses "CONSOLE"
randomize
DECLARE function SetupMap LIB "C:\Dev\test1.DLL" ALIAS "SetupMap" (byval arrayhandle as long, byval Width as long, byval Height as long, byval Diag as long) as long
DECLARE function FindPath LIB "C:\Dev\test1.DLL" ALIAS "FindPath" (byval StartX as long, byval StartY as long, byval DestX as long, byval DestY as long) as long
DECLARE function GetRoute LIB "C:\Dev\test1.DLL" ALIAS "GetRoute" ( length as long) as long
const _SIZE as long = 10
dim pMapArr as long
pMapArr = heap_alloc(_size * _size * sizeof(LONG)) '---<<<< ALLOCATE memory
dim i,j as integer
dim arr(_SIZE,_SIZE) as single at pMapArr
dim a,b,c,d,e as long
''dim f() as long
a=_SIZE
b=_SIZE
c=2
'// Create test map with random val [0.0,1.0]
for i = 1 to _SIZE
for j = 1 to _SIZE
arr(i,j) = rnd
print(i,j,arr(i,j), $crlf )
next
next
print SetupMap(pMapArr,_SIZE,_SIZE,2) , $crlf '// pass the map
'print SetupMap(pMapArr,a,b,c), $crlf
sleep(500)
Print FindPath(0,0,8,8), $crlf '// call pathfinder
sleep(500)
d=GetRoute(e) '// [e] is length of the route, [d] is the array pointer
print e, $crlf
dim f(e) as long at d '// create an array of [e] size and point to addr [d]
print f(1), $crlf '// print first element of patharray [its giving a large long value rather than the coord]
waitkey
ErosOlmi
17-02-2009, 08:51
Ok, perfect. Just few notes.
If you have no real reasons why using DIM ... AT ... statement, you can use standard DIM:
dim arr(_SIZE,_SIZE) as single
and when you need to pass array pointer to your Setup function you can use VARPTR (http://www.thinbasic.com/public/products/thinBasic/help/html/varptr.htm) in this way:
SetupMap(VARPTR(arr), _SIZE, _SIZE, 2)
Instead of using something like:
PRINT whatever, $CRLF
to print something plus a new line, you can use PRINTL that automatically will advance the cursor to the next line:
PRINTL whatever
Ciao
Eros
MouseTrap
17-02-2009, 09:24
Thanks!
those are good tips!