PDA

View Full Version : Integrating thinBasic with NeoBook



ReneMiner
28-09-2013, 19:47
I post this in the name of some other user - David (http://www.thinbasic.com/community/member.php?u=1615) - who's not able to post it himself somehow...
---------------------------------------------------------------------------------------------

Hi thinBasic team,

My Name is David, and i'm pleased to be in your Forum.

I'm NeoBook (http://www.neosoftware.com) and PowerBasic programmer.

NeoBook is a RAD written in Delphi. It has its own dialect programming.

NeoBook has the capability to connect with another languages ( VBScript, Javascript,etc) via Scripts and with other Compiled languages (C, Delphi, PowerBasic) following a SDK.

With this compiled languages, is possible create some kind of Dll's, that works as plugins, growing the capabilities of NeoBook.

When i discovered your BINT32 library, i addapted it in order to use with NeoBook.

This link is a sample how works your library:

http://www.neobook.com.ar/files/DemoBint32.zip

Main Program is written with Neobook, the wrapper of your library is written in PowerBasic.

At this time, program can do:

a) Reset all BINT32 library.
b) Read a Script file (or select it)
c) Set the Script variable values before run the script
d) Run the script
e) Get the Script variable values after run the script

The values of the variables are sent and received using the SDK interface, and can be handled by the NeoBook user into his main program.



Now, i discovered thinBasic, is fantastic !

I'm trying to do a similar program in PowerBasic, to get the potential of your program.

My principal code is: (if you need all program, feel free to ask me...)


////////////////////////////////////////////////////////////////////

#COMPILE DLL "NeoPBThinBasic"
#INCLUDE "Win32Api.inc"
#INCLUDE "ThinCore.inc"

.....

' send variable value to NeoBook enviroment

SUB SetVariable(BYVAL Variable$,BYVAL vuelta$)
CALL DWORD nbSetVar USING SetVarProcType(BYCOPY variable$, BYCOPY vuelta$)
END SUB

.........

Function File_load (File as string) as string
Local tempstr as string
OPEN File FOR BINARY AS #1
x&& = LOF(1)
GET$ #1, x&&, tempstr
CLOSE #1
setvariable "ae_TB_FileData", tempStr
Function = tempstr
End Function

'--------------------------------------------------------------------
' d1 = Text or file.txt (input)
' d2 = kind of input (text or file) (input)
' Buffer & Source are globally defined as string

'--------------------------------------------------------------------

FUNCTION ae_TB_Init () EXPORT AS BYTE
hInst = GetModuleHandle(ByVal %NULL)
hScript = thinBasic_Init(byval 0, hInst,"")
setvariable "ae_TB_hScript", str$(hScript)
setvariable "ae_TB_hInst", str$(hInst)
End Function

'--------------------------------------------------------------------

FUNCTION ae_TB_End () EXPORT AS BYTE
thinBasic_Release(hScript)
End Function

'--------------------------------------------------------------------


FUNCTION ae_TB_Run (d1 AS ASCIIZ, d2 AS ASCIIZ) EXPORT AS BYTE
Buffer = D1
Source = D2
If Source = "F" Then
CALL thinBasic_Run(0, FILE_Load(Buffer), %thinBasic_BufferType_IsFile, 1 Or 2, %FALSE, %FALSE, %FALSE, 1, %FALSE)
Else
CALL thinBasic_Run(0, Buffer, %thinBasic_BufferType_IsScript, 1 Or 2, %FALSE, %FALSE, %FALSE, 1, %FALSE)
End if
END FUNCTION


'--------------------------------------------------------------------
' d1 = PB Var Name (input)
' d2 = PB Var Type; N->Numeric, S->String (input)
' d3 = NeoBook Variable Name (output)

FUNCTION ae_TB_GetVar (d1 AS ASCIIZ, d2 AS ASCIIZ, d3 AS ASCIIZ) EXPORT AS BYTE
Local var1 as string, var2 as string, var3 as string, result as string
Var1 = D1
Var2 = D2
Var3 = D3

if Var1 > "" then
if Var2 = "N" then
Result = str$(thinBasic_VariableGetValueNum(Var1))
replace " " with "" in Result
SetVariable Var3, Result
Else
'SetVariable Var3, BINT_GetString(Var1)
End if
End if

END FUNCTION


'--------------------------------------------------------------------
' d1 = PB Var Name (input)
' d2 = PB Var Value (input)
' d3 = PB Var Type; N->Numeric, S->String (input)

FUNCTION ae_TB_SetVar (d1 AS ASCIIZ,d2 AS ASCIIZ,d3 AS ASCIIZ) EXPORT AS BYTE
Local dd1 as string, dd2 as string, dd3 as string
Local Number AS EXT

dd1 = d1
dd2 = d2
dd3 = d3

If dd3 = "N" Then
number = val(dd2)
CALL thinBasic_ChangeVariableNumber(dd1, number)
Else
CALL thinBasic_ChangeVariableString(dd1, dd2)
End IF
END FUNCTION


/////////////////////////////////////////////////////////////////////////////



At the ae_TB_Init () function i use 2 variables:
- hScript
- hInst
Defined as Global Long

The following line:


hScript = thinBasic_Init(byval 0, hInst,"")

returns hScript value = -1

After this action, nothing works fine.

The principal purpose of my PowerBasic plugin program, is be a bridge between NeoBook and your thinCore.DLL library, for send and receive variable values.

Are there any way to do something like the sample i sent you, but using your thinCore.DLL library ?

Perhaps i need do some special registration, a payment ?

Any ideas ?

Thanks in advance,
Greetings from Buenos Aires, Argentina
David Marcovich

David
28-09-2013, 20:39
Hello all !

Finally, here we are !

Thanks Rene & Eros !

Greetings from Buenos Aires, Argentina
David

David
28-09-2013, 20:45
Thanks George Deluca @ PowerBasic Forum:


hScript = thinBasic_Init(0,hInst,"thinbasic")

a problem solved.

Goto next problem.

David

David
28-09-2013, 20:54
Well, i can put in work the thinCore.dll.

In fact, i can run several thinBasic Scripts. not all... for the moment.

New Problem:

After run the script, when close windowed script, i execute this function:


thinBasic_Release(0)

Script is stopped, window is closed, but does not resume the main program...

Any ideas ?

Thanks in advance,
David

ErosOlmi
29-09-2013, 00:59
Here a PowerBasic pirce of code of how to execute a thinBasic script from a PB program



'----------------------------------------------------------------------------
Function thinAir_Scripting_Run( _
ByVal sEmbedded_Script_Main As String _
) As Long
'----------------------------------------------------------------------------
Local lRet As Long


'---Init thinCore engine
thinBasic_Init( _
0& , _ 'Future usage
gApplication.hInst , _ 'Instance passed from OS to the application usually in Main function
"thinBasic" _ 'Always pass "thinBasic" string
) To lRet

'---If all went fine during initialization ...
If lRet >= 0& Then


'---Load new keywords
thinBasic_LoadSymbol "thinAir_MDI_Count" , %thinBasic_ReturnNumber , CodePtr(Exec_thinAir_Scripting_MDI_Count) , %thinBasic_ForceOverWrite
thinBasic_LoadSymbol "thinAir_MDI_GetFullFileName" , %thinBasic_ReturnString , CodePtr(Exec_thinAir_Scripting_MDI_GetFullFileName) , %thinBasic_ForceOverWrite



'---Run the program
thinBasic_RUN( _
0& , _ 'Will be used in future release
sEmbedded_Script_Main , _ 'File name or string Buffer
1& , _ '0 = previous string is a File Name, 1 = previous string is a string Buffer
1 Or 2 , _ '1=use EXE path, 2=avoid PostQuitMessage in case of RTE
%FALSE , _ 'Debug Mode %TRUE/%FALSE
%FALSE , _ 'Log Mode %TRUE/%FALSE
%FALSE , _ 'Obfuscate Mode %TRUE/%FALSE
0& , _ 'Calling Program 1=thinBasic, 2=Console
%FALSE _ 'Dependancy Mode %TRUE/%FALSE
) To lRet

'---Unload all, release memory
thinBasic_Release( _
0& _ 'Will be used in future release
) To lRet


End If


End Function



Mainly always execute:

thinBasic_Init
...if necessary ... thinBasic_LoadSymbol
thinBasic_RUN
thinBasic_Release

David
30-09-2013, 08:17
Thanks a bunch Eros !

Program begins to work...

New Problem:

From the Main (NeoBook) program, i need get the variable values, to evaluate and do the process according results...

To get the variable values, at the PowerBasic Program, i do:


FUNCTION ae_TB_GetVariableInfo (d1 AS ASCIIZ, d2 AS ASCIIZ) EXPORT AS BYTE
' d1 = Script Var Name
' d2 = Return Var
local ReturnVar as String, SearchKey as String, SResult as String
Local Result as Long, MainType as Long, SubType as Long, IsArray as Long

' get te received parameters
SearchKey = d1
ReturnVar = d2

thinBasic_VariableGetInfo ( BYVAL SearchKey, BYREF MainType, BYREF SubType, BYREF IsArray ) to Result

IF MainType = 20& Then 'is a Number
thinBasic_VariableGetValueNum(SearchKey) to Result
MSGBox str$(MainType) + " " + str$(Result)
Else
thinBasic_VariableGetValueStr(SearchKey) to Result <-- Here the problem
MSGBox str$(MainType) + " " + Result
End if

End Function



This Function works fine with numeric variables
I don't know if function does not exist or if i'm missing something...
I can't find the way to get the value of a String Variable.

Could any help me ?

Thanks in advance,
David

ReneMiner
30-09-2013, 08:41
perhaps you can find in this function some hint (code: thinBasic)




%TYPE_String = 30

Declare Function Variable_GetInfoEX _
Lib "thinCore.DLL" _
Alias "thinBasic_VariableGetInfoEX" _
( _
ByVal SearchKey As String , _
ByRef MainType As Long , _ '---ATTENTION: parameter passed BYREF will return info
ByRef SubType As Long , _ '---ATTENTION: parameter passed BYREF will return info
ByRef IsArray As Long , _ '---ATTENTION: parameter passed BYREF will return info
ByRef DataPtr As Long , _ '---ATTENTION: parameter passed BYREF will return info
ByRef nElements As Long , _ '---ATTENTION: parameter passed BYREF will return info
Optional _
ByVal WhichLevel As Long _
) As Long


Function VARIABLE_GetData( ByVal sName As String, _
Optional Index As Long, _
lSize As Long _
) As String

' mainly use on simple variables and arrays of any type
' returns content of variable passed by name or ""

' pass an Index to get Data of a certain Array-Element

' pass as lSize
' SizeOf(<Some Type>) ALWAYS if it is not a String/String-Array

' on Strings/String-Array
' can use Len(<Some String>) if you want just the Left$-part

If Not VARIABLE_Exists(sName) Then Return ""

Local lMainType, lSubType, lIsArray, lDataPtr, lnElements As DWord
Local realPtr, realSize As DWord

VARIABLE_GetInfoEx(sName, lMainType, lSubType, lIsArray, lDataPtr, lnElements)

If All( _
lIsArray <> 0, _
Between(Index, 1, lnElements) _
) Then
If lMainType = %Type_String Then
realPtr = Peek(DWord, lDataPtr + (Index - 1) * 4)
realSize = Peek(DWord, realPtr - 4)
If realSize = 0 Then Return ""
If Between(lSize, 1, realSize) Then
Function = Memory_Get(realPtr, lSize)
Else
Function = Memory_Get(realPtr, realSize)
EndIf
ElseIf lSize > 0 Then
Function = Memory_Get(lDataPtr + (Index - 1) * lSize, lSize)
EndIf
Else
If lMainType = %Type_String Then
realPtr = Peek(DWord, lDataPtr)
realSize = Peek(DWord, realPtr - 4)
If realSize = 0 Then Return ""
If Between(lSize, 1, realSize) Then
Function = Memory_Get(realPtr, lSize)
Else
Function = Memory_Get(realPtr, realSize)
EndIf
ElseIf lSize > 0 Then
Function = Memory_Get(lDataPtr, lSize)
EndIf

EndIf

End Function


Edit: The Attachement is some older version mostly about heap- but inside you could find more of these variable-functions for studying

David
30-09-2013, 10:19
WOW !

Nice people, nice Forum !

Thanks Rene, after adapt your function, works like a charm...

Next problem: (don't hate me...)

Supose this Script:


Dim StrVar as string
MSGBox (0, "Hello World, hello " & StrVar)

User needs to set the StrVar before execute the script, in order the MSGBox tells "Hello World, Hello YourName..."

I had checked the:

thinBasic_ChangeVariableString
thinBasic_ChangeVariableNumber

Works fine, but after the script is executed.

Could any tell me about the purpose of change variable values after the script is executed ?

On the sample, are there any way to change the variable values before the script is executed ?

I guess no, because the script is procesed on the thinBasic_Run time, not before, I don't find any "thinBasic_LoadScript" function that allows do some variable value changes...

Any ideas ?

Thanks in advance,
David

ReneMiner
30-09-2013, 12:08
If you got the variables/data position in memory you can easily Dim yourVar As yourType At thisPosition - so tB not necessarily needs to allocate own variables if they are already known "outside" - tB just needs to know where to find these to share them. This would allow to set them up before running. Is also faster because no local memory-allocation nor time to reorder memory is needed.

ErosOlmi
30-09-2013, 14:17
The way is to inject thinBasic execution with your own command and call them inside the script.
You can add any number of new commands using "thinBasic_LoadSymbol"

See \thinBasic\SDK\ examples on how to create thinBasic modules.
The same technique can be used when you use thinBasic as scripting engine.

David
30-09-2013, 20:17
Thanks Eros,

I had created a bridge function to "thinBasic_LoadSymbol" and works fine.
But no variables were listed using "thinBasic_VariableGetList"

Rene:

Could you put a small sample how to share the address ?

Based on the sample, the tB Script should be something like


Dim MyVar as string At thisPosition
MsgBox (0, "Hello World, hello " & MyVar)


I guess PB code should be something like


' Source (d2) & Buffer (d1) are global variables as string

thinBasic_Init(0, GetModuleHandle(ByVal %NULL), "thinBasic")
Local MyAddress as dword, thisPosition as dword, MyVar as string
If Source = "F" Then
Local File as string
File = d1
OPEN File FOR BINARY AS #1
GET$ #1, LOF(1), Buffer
CLOSE #1
Else
Buffer = d2
End if

MyAddress = StrPTR(Buffer)
thinBasic_LoadSymbol "Hello", %thinBasic_ReturnNone, MyAddress, %thinBasic_ForceOverWrite

MyVar = "David"
thisPosition = VarPtr(MyVar)

' .... ? ...

thinBasic_Run( 0&, Buffer, 0, 1 or 2, %FALSE, %FALSE, %FALSE, 0, %FALSE)



How do i do to send the "thisPosition" address to the thinBasic structure ?
Using thinBasic_AddVariable Function ?

Thanks in advance,
David

ReneMiner
30-09-2013, 20:40
Sorry- I guess I lead you on wrong track here - I thought you would do something like running external propgram- start tB-script from there and this works with your in external program preset variables. But - you could probably add an Equate or Variable containing the pointer to a PB-Variable - only thing I fear dynamic strings are not as easy to handle - if the PB-variable is a string tB might read it but changing it will be limited to the initial len - changing/redim variable from PB could also make an equate invalid - one has to poke a new value there.
I would just put the VarPtr or StrPtr into some added equate or variable where to find the data - if no other idea pass it just via Clipboard or in a file...

- to have strings local read out from myStrPtr use like

txt = Memory_Get(myStrPtr, Peek(DWord, myStrPtr - 4))

overlay to dynamic string itself won't work if you just place another dynamic string over but some fixed to same len or shorter - so you would need the len alike

Dim myVar As String * Peek(DWord, myStrPtr -4) At myStrPtr
- so easier to read out content just like above...

David
01-10-2013, 00:30
Well, not all works as espected....

This requires force brute.

I solved the set parameters problem changing the script loaded into memory, based on a replacement of some tags i defined into script to be changed like: (.tScript Code)


DIM Message AS STRING
DIM MsgTitle AS STRING
DIM MsgStyle AS STRING
DIM YourName AS STRING Value "Noname"
DIM MaxLoops AS LONG VALUE 1000

'-------------------------------------------------------------------------------------
' Following Lines will be replaced with the variable values
' You must include into your Script.
' as the lines are commented, nothing is executed from thinBasic
' Syntax must be exact; like '<VarName>
'-------------------------------------------------------------------------------------

'<YourName>
'<MaxLoops>


Message = "Hello " & YourName & Chr$(13,10) & "Maxloops = " & str$(MaxLoops)

MsgTitle = "My MsgBox"
MsgStyle = "ICONINFORMATION"
MSGBOX(0,Message,MsgStyle,MsgTitle)


I solved with this function: (PB Function)


'--------------------------------------------------------------------
' d1 = PB Var Name (input)
' d2 = PB Var Value (input)
' d3 = PB Var Type; N->Numeric, S->String (input)
' Buffer is Global String defined, and procesed in another function
'--------------------------------------------------------------------
FUNCTION ae_TB_SetVar (d1 AS ASCIIZ,d2 AS ASCIIZ,d3 AS ASCIIZ) EXPORT AS BYTE
Local dd1 as string, dd2 as string, dd3 as string, MatchString as string, NewString as string
Local Number AS EXT

dd1 = d1
dd2 = d2
dd3 = d3

MatchString = "'<" & dd1 & ">"
if dd3 = "N" then
NewString = dd1 & " = " & dd2
Else
NewString = dd1 & " = " & chr$(34) & dd2 & chr$(34)
End if
Replace MatchString WITH NewString IN Buffer
' send the new script code to NeoBook
SetVariable "ae_TB_Data", buffer
END FUNCTION




Now, almost all works fine....

Except

An odd behavior when script is closed.

* all scripts that uses Console, produces a runtime error
* All Windowed Scripts, that not includes %WS_SYSMENU or equivalent, produces a runtime error

Program closes, Parent program closes, and i can't find the way to trap the error and handle.

Any ideas ?

Thanks again, and again..... and again,
David

David
02-10-2013, 01:06
Hello guys,

I'm proud to announce the first beta of the plugin.

You can the info and the download link at:

http://neosoftware.com/community/viewtopic.php?f=3&t=20173

If you test it, please use the samples attached into the zip, because some of them has changes.

There are 3 EXE into the zip, you can use them directly, without install NeoBook

Thanks ! Thanks ! Thanks !

David

David
02-10-2013, 19:02
Are overthere any Peak level or vumeter sample to addapt ?

Thanks in advance
David