View Full Version : Embedded - supported or not?
gddeluca
13-03-2013, 19:59
Hi,
I've been using the old BInt32 code as an embedded script engine. I'd like to switch to thinBasic because the language itself is so much better.
The .INC file contents SEEM to indicate the same kind of support/interface as BInt32 did, but there's no doc anywhere, and my attempts at guessing based on my BInt32 usage have been utter failures.
Has anyone done this? Any sample code? Eros seemed to indicate the support was there but he hadn't time to document it.
It seems so tantalizingly close.
George
Petr Schreiber
14-03-2013, 10:23
Hi George,
the embedding mechanism is provided by the thinBasic_Init, thinBasic_Run and thinBasic_Release functions at the moment, which basically launch the script on demnad with some configuration options. I think this is the mechanism thinAIR uses to launch scripts, but Eros will know better.
These functions are present in thinCore.DLL and they are defined in thinBasic/SDK headers.
There was not a lot of demand for embedding lately, so other areas got priority. I think we could discuss what you would expect from the embeddable language and maybe the further steps could be taken to make thinBASIC more embed-friendly.
The "problem" is that thinBASIC became quite capable very fast, so many of us started thinking of it more as of standalone language than simple embeddable helper like BINT32 is :)
Petr
largo_winch
14-03-2013, 12:57
you can use the buffer for interpreting as all bint examples shows in example folder so far I can remember. you have only make "bint_run" function for interpreting buffer string. I have tried last years for studying without any problems. I cannot find my example at work. if I find the script I can say more.
bye, largo
gddeluca
14-03-2013, 18:03
Hi Petr,
Yes, the thinBasic functions are extremely similar to what I have currently working with BInt32; that's why it seems such a small step to move over to thinBasic. However, the thinCore.INC files have absolutely no instructions or comments regarding their use. And there are new parameters being passed to the functions but no help as to what they are supposed to be. Can you shed any light on actually what some of the following parameters are, or how used. thinBasic_Run I'm fine with, it looks just like the BInt32 equivalent call, but thinBasic_Init and thinBasic_Release are both new. Like what are hWnd, cInstance, sKey and hScript? I've been trying to guess, but so far all it gets me is a variety of crashes.
Declare Function thinBasic_Init _
Lib "thinCore.dll" _
Alias "thinBasic_Init" _
( _
ByVal hWnd As Long , _
ByVal cInstance As Long , _
ByVal sKey As String _
) As Long
Declare Function thinBasic_Release _
Lib "thinCore.dll" _
Alias "thinBasic_Release" _
( _
ByVal hScript As Long _
) As Long
Declare Function thinBasic_Run _
Lib "thinCore.dll" _
Alias "thinBasic_Run" _
( _
ByVal hScript As Long , _
byval sBuffer As string , _
ByVal BufferType As Long , _
Optional ByVal Options As Long , _
ByVal DebugMode As Long , _
ByVal LogMode As Long , _
ByVal ObfuscateMode As Long , _
ByVal CallingProgram As Long , _
ByVal DependancyMode As Long _
) As Long
George
Hi George,
the embedding mechanism is provided by the thinBasic_Init, thinBasic_Run and thinBasic_Release functions at the moment, which basically launch the script on demnad with some configuration options. I think this is the mechanism thinAIR uses to launch scripts, but Eros will know better.
These functions are present in thinCore.DLL and they are defined in thinBasic/SDK headers.
There was not a lot of demand for embedding lately, so other areas got priority. I think we could discuss what you would expect from the embeddable language and maybe the further steps could be taken to make thinBASIC more embed-friendly.
The "problem" is that thinBASIC became quite capable very fast, so many of us started thinking of it more as of standalone language than simple embeddable helper like BINT32 is :)
Petr
ErosOlmi
16-03-2013, 13:55
Hi George,
first of all, thanks to be here in thinBasic community forum.
I'm sorry but the actual status of thinBasic is not perfect for embedding into 3rd party applications.
But together maybe we will be able to add all the necessary/wished functionalities.
Regarding the 3 main functions, I will document in next thinBasic release.
Here below an example (using PowerBasic as programming language) that should gives you an idea.
Let me know.
Eros
...
Local hLib_thinCore As Long 'Handle of thinCore.dll library
Local hProc_thinBasic_Init As Long 'Handle to Init function
Local hProc_thinBasic_Run As Long 'Handle to Run function
Local hProc_thinBasic_Release As Long 'Handle to Release function
Local lRet As Long
'---Open and load thinCore.dll library
hLib_thinCore = LoadLibraryA( ByCopy "thinCore.Dll" )
'---If all went fine
If hLib_thinCore Then ...
'---Try to load Init, Run, Release functions
hProc_thinBasic_Init = GetProcAddress(hLib_thinCore, ByCopy "thinBasic_Init" )
hProc_thinBasic_Run = GetProcAddress(hLib_thinCore, ByCopy "thinBasic_Run" )
hProc_thinBasic_Release = GetProcAddress(hLib_thinCore, ByCopy "thinBasic_Release" )
'---If all went fine ...
If hProc_thinBasic_Init And _
hProc_thinBasic_Run And _
hProc_thinBasic_Release Then
'---Initialise all necessary variables
Call Dword hProc_thinBasic_Init Using thinBasic_Init( _
0& , _ 'Future usage
hCurInstance, _ 'Instance passed from OS to the application usually in Main function
"thinBasic" _ 'Always pass "thinBasic" string
) To lRet
'---If all went fine ...
If lRet >= 0& Then
'---Run the program
Call Dword hProc_thinBasic_Run Using _
thinBasic_RUN( _
0& , _ 'Will be used in future release
sEmbedded_Script_Main , _ 'File name or string Buffer
%thinBasic_BufferType_IsScript , _ '0 = previous string is a File Name, 1 = previous string is a string Buffer
0 , _ 'Options, set it to zero
%FALSE , _ 'Debug Mode %TRUE/%FALSE
%FALSE , _ 'Log Mode %TRUE/%FALSE
%FALSE , _ 'Obfuscate Mode %TRUE/%FALSE
1& , _ 'Calling Program 1=thinBasic, 2=Console
%FALSE _ 'Dependancy Mode %TRUE/%FALSE
) To lRet
'---Unload all modules, release all memory
Call Dword hProc_thinBasic_Release Using thinBasic_Release( _
0& _ 'Will be used in future release
) To lRet
End If
End If
'---Free loaded thinCore library
FreeLibrary(hLib_thinCore)
End If
gddeluca
16-03-2013, 20:37
Hi Eros,
Super! Many, many thanks. This looks SO CLOSE to what I've been using to access BInt32, I knew it should be possible. I've been using BInt32 for a while, (fixed a few minor bugs in there) but thinBasic sure looked appealing.
I'll give this a try.
Is there any hope that equivalents to BInt32_ErrorDescription(), BInt32_ErrorGetToken and Bint32_ErrorGetLine) also exist?
George
gddeluca
16-03-2013, 21:38
Hi again,
Ignore my last question, the normal error popup is more than adequate.
Is there any hope that equivalents to BInt32_ErrorDescription(), BInt32_ErrorGetToken and Bint32_ErrorGetLine) also exist?
George
ErosOlmi
17-03-2013, 12:17
Dear George,
you can use thinBasic_ErrorFree after thinBasic_RUN to check if execution generated a run-time error.
In next thinBasic version (I'm just working on it) if you set "Log Mode" to %TRUE in thinBasic_RUN, in case of run-time error thinBasic will create a file into %TEMP%\ directory called with the same name of the script but with estension ".log"
This file will have a structure like an INI file and will contain something like that:
[Script]
Main=<name of the main script>
Include=<in case of error occurred into an included script, name of the included script>
[RunTimeError]
DateTime=17/03/2013 10:40:38
Code=<error code>
Description=<error description>
Line=<line number where error occurred>
LineCode=<full line of the script where error occurred>
Token=<first token in the line where error occurred>
Additional=<optional additional info arrived from run-time error>
gddeluca
17-03-2013, 17:51
Hi Eros,
Sounds good. What you provided in your previous note was great, I've managed to swap my App from Bint32 to thinBasic with almost no code changes other than the function renames. Your help is much appreciated.
George
ErosOlmi
17-03-2013, 18:17
Great.
If you like, giving more details on how you use thinBasic as embedded language can give me more info on how to improve thinBasic Core engine.
In my mind, the idea to embed a programming language into a main application is to perform operations on the main application.
More or less like having VBA in Office applications (pass me the comparison: VBA is much powerful than thinBasic).
Is this the case?
Thanks
Eros
gddeluca
17-03-2013, 19:49
Hi Eros,
Exactly how I am using it. I'm using it as the macro engine for an Editor. A variety of user functions are used to provide the API between the script and the application itself. It works very well. Even before, when using BInt32, it was more than capable of handling the scripting requirements. Now that I have thinBasic running as the engine, it's even more powerful. But I've uncovered one oddity. If I issue a USES to bring in another module (like FILE) it works fine. But if I simply re-run the macro/script again, the USES fails with a return code of -3 saying the module is already loaded. It seems thinBasic_Release() is not releasing the DLL. Even though -3 says it's still loaded, it actually isn't and an attempt to use, say, FILE_Exists fails.
So right now, other than using the CORE functionality (which is still great!) access to all the other modules is effectively curtailed as it requires a restart of the main App to get rid of the FILE DLL. Is this just a code oversight? Or a design flaw?
Beyond that, it seems to run embedded exactly as I would like and has been extremely simple to create the interface. It is a joy to work with.
George
Great.
If you like, giving more details on how you use thinBasic as embedded language can give me more info on how to improve thinBasic Core engine.
In my mind, the idea to embed a programming language into a main application is to perform operations on the main application.
More or less like having VBA in Office applications (pass me the comparison: VBA is much powerful than thinBasic).
Is this the case?
Thanks
Eros
ErosOlmi
17-03-2013, 20:35
Do you Init/Run/Release every time you execute a script?
gddeluca
17-03-2013, 20:51
Hi,
Yes, Init, a bunch of LoadSymbols, Run, and Release. It is basically the sample code you provided, including the FreeLibrary of thinCore.DLL at the end.
In my test script, the return code from USES for the first run is 20 (?) and for a second run is -3.
George
Do you Init/Run/Release every time you execute a script?
ErosOlmi
17-03-2013, 21:01
Ok, thanks.
so you are developing your internal functions and mapping them using thinBasic_LoadSymbol after thinBasic_Init.
Theoretically it should work ;)
I say "Theoretically" because no-one reported me so far to have tried that way.
20 as return code is not good.
I need few more info:
what modules are you loading with USES ...
where are you placing thinBasic modules relatively your main Application?
I mean, if your application is placed in something like C:\MyApp\MyEditor.exe
where are thinBasic module placed? C:\MyApp\.....
You should place the thinBasic modules you need under your main Application directory under one of the following directories:
"Lib\"
"Bin\"
"Mod\"
Thanks
Eros
PS: I will move this thread under another forum: http://www.thinbasic.com/community/forumdisplay.php?358-thinBasic-SDK
gddeluca
17-03-2013, 21:33
Hi,
Is there a preferred sequence for Init/LoadSymbol/Run? It seems to work just fine as I'm doing it.
If RC=20 is not good, it doesn't seem to affect use of the DLL functions. I'm doing a USES "FILE" and then calling FILE_Exists and it seems to work just fine.
Not having USES right now is not a serious problem, the functions in CORE are all that is truly NEEDED. I just wanted to try out USES so that I'd know any implications before questions start coming in from my own users.
I originally had just thinCore.DLL in the same folder as my own App EXE, but when I was going to try out the USES facility, I thought it better to leave them in your thinBasic install locations. So I have added the thinBasic folder and thinBasic\LIB folders to my PATH. I thought it best for final installer considerations to just tell my users to install thinBasic as normal, add them to the path, and then do the install of my App. Do you have any concerns, ideas, etc. as to what would be the best method of coordinating this? I can, of course just place everything in my own install directories, but I thought it best to keep thinBasic and my own Apps modules apart for maintenance reasons.
George
Ok, thanks.
so you are developing your internal functions and mapping them using thinBasic_LoadSymbol after thinBasic_Init.
Theoretically it should work ;)
I say "Theoretically" because no-one reported me so far to have tried that way.
20 as return code is not good.
I need few more info:
what modules are you loading with USES ...
where are you placing thinBasic modules relatively your main Application?
I mean, if your application is placed in something like C:\MyApp\MyEditor.exe
where are thinBasic module placed? C:\MyApp\.....
You should place the thinBasic modules you need under your main Application directory under one of the following directories:
"Lib\"
"Bin\"
"Mod\"
Thanks
Eros
PS: I will move this thread under another forum: http://www.thinbasic.com/community/forumdisplay.php?358-thinBasic-SDK
ErosOlmi
17-03-2013, 21:55
The correct situation for developers wanting to use thinBasic as embedded engine should be:
distribute thinCore.dll with your application placing it in the same directory of your main app.
distribute the thinBasic modules you want distribute placing them into one of the following sub-directories under your main application directory: "Lib\" or "Bin\" or "Mod\"
So (for example) something like the following:
.\MyApplication.exe
.\thinCore.dll
.\Bin\thinBasic_UI.Dll
.\Bin\thinBasic_Trace.Dll
Anyway, I will make some test application embedding thinCore.dll and see.
Thanks for using thinBasic.
Ciao
Eros
gddeluca
23-04-2013, 18:27
Eros: Any news at all as to why I cannot USE any of the other modules other than CORE more than once? I can survive using only CORE functions, but I'm sure my users, once they start exploring thinBasic usage as an embedded macro language, are for sure going to ask why they can not have access to the remaining set of modules.
Is there any release/free function I could insert in my main code? I could certainly scan for the USES and determine what modules need to be processed.
George
ErosOlmi
25-04-2013, 16:12
George,
did you follow my indication to create a \Bin\ directory under you main EXE and place module in there?
Was that indication working or not?
Let me know.
Eros
gddeluca
25-04-2013, 17:09
Eros:
If I put the module's DLL in a /Bin directory under the EXEPath directory, then thinBasic does not seem to find the DLL at all.
If I put the module's DLL directly IN the EXEPath directory, then the DLL is found and a call to a function within it works perfectly.
e.g. my app calls thinBasic to run the script, the script successfully USES and calls a function in the module's DLL, and the script terminates normally via a STOP command.
If I then, without restarting my main app, repeat the call to run the script, the call to the DLL module fails.
If I restart my app again, I can invoke the script, with its USES DLL call once and only once. As I indicated earlier, the error is returned by the USES command (the USES fails with a return code of -3 saying the module is already loaded), which seems to indicate that thinBasic has not quite cleaned up the linkages from the first use of the DLL.
George
ReneMiner
25-04-2013, 20:06
Just some experience - won't interfere - so don't bother if not of your interest.
My safe way to create .exe of something that needs a "foreign" dll:
Add .dll to bundle, (sometimes .dll disappears after bundling - but then i just replace it) - sometimes does not disappear - I don't care - I'm used to it.
But as long as .dll is in same path as .tBasic-script is - and also if .dll gets bundled into the .exe I have no problems.
If I ship .dll seperate from bundled exe or .dll is not at same path as .tBasic-script - does not work always as expected - so I stick to keep .dll next to .tBasic-script on same path, and if bundling - always add .dll into the bundle. Never had any problems that way.
ErosOlmi
05-05-2013, 21:14
Eros:
If I put the module's DLL in a /Bin directory under the EXEPath directory, then thinBasic does not seem to find the DLL at all.
If I put the module's DLL directly IN the EXEPath directory, then the DLL is found and a call to a function within it works perfectly.
e.g. my app calls thinBasic to run the script, the script successfully USES and calls a function in the module's DLL, and the script terminates normally via a STOP command.
If I then, without restarting my main app, repeat the call to run the script, the call to the DLL module fails.
If I restart my app again, I can invoke the script, with its USES DLL call once and only once. As I indicated earlier, the error is returned by the USES command (the USES fails with a return code of -3 saying the module is already loaded), which seems to indicate that thinBasic has not quite cleaned up the linkages from the first use of the DLL.
George
Dear George,
I just released thinBasic Beta 1.9.6.0
With this release I hope I fixed the problem you mentioned.
I also added two options that can be useful.
When you call thinBasic_RUN please indicate as Option parameter the following: 1 Or 2
Option parameter is a bit flag used to pass multiple options.
1 Or 2 means switch bit 1 and 2
1 = to consider as base directory the one of the executable running thinBasic_Run and not thinBasic itself
2 = in case of script run-time error, do not close calling application too. If this option is omitted, thinBasic runtime error engine will fire a PostQuitMessage in case of runtime error.
Below an example:
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 , _ 'Options, set it to zero
%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
Let me know if problems related to modules are now solved.
Remember to put modules you want to distribute into one of the following path:
<yourapplicationpath>\mod\
<yourapplicationpath>\lib\
Ciao
Eros
gddeluca
12-05-2013, 17:49
Eros: Regarding the new Options flag setting on the RUN call. I guess I'm not getting this. Are they bit flags within a LONG parameter. I've tried all flavors of passing values, and I cannot seem to get any through (e.g. the PostQuit message is always sent on a syntax error).
I've tried passing simple literal values, I've tried setting up an Options variable and setting various bits in it and passing the variable. Nothing seems to have any effect.
I'd like to utilize both Options 1 and 2, what exactly should be coded? I'm stumped.
George
ErosOlmi
12-05-2013, 22:17
They are Bit flags inside a LONG parameter.
To use both you need to pass: 1 OR 2
gddeluca
13-05-2013, 16:52
Eros: Here's what I'm trying.
CALL DWORD hProc_thinBasic_Run USING thinBasic_RUN( _
0& , _ 'Will be used in future release
BasicPgm , _ 'File name or string Buffer
%thinBasic_BufferType_IsScript , _ '0 = previous string is a File Name, 1 = previous string is a string Buffer
(1 OR 2) , _ 'Options
%FALSE , _ 'Debug Mode %TRUE/%FALSE
%FALSE , _ 'Log Mode %TRUE/%FALSE
%FALSE , _ 'Obfuscate Mode %TRUE/%FALSE
1& , _ 'Calling Program 1=thinBasic, 2=Console
%FALSE _ 'Dependancy Mode %TRUE/%FALSE
) TO lRet
I still get a popup from PowerBasic giving a RUNTIMEERROR 1 message; which is, I assume, triggered by the PostQuitMessage; indicating it is still being issued. I'm doing the thinBasic call from a thread of my main program in case that matters at all. I do that so I can monitor for possible loops in the macro code and give my user a chance to terminate the embedded macro instead of having to cancel my whole application, which for an editor, is not too cool an option.
Also, my PB program is written in DDT not SDK mode if that makes any difference.
Right now this is only a nuisance, clicking OK on the RUNTIMEERROR popup dismisses it and my program continues OK But it would be nice to get rid of it.
George
ErosOlmi
13-05-2013, 18:34
Please check this bug reported immediately by Petr. We fixed it very soon but I suppose you download version 1.9.6 just before. So please download thinBasic beta 1.9.6 again and let me know. http://www.thinbasic.com/community/project.php?issueid=398#note2430
gddeluca
13-05-2013, 20:28
Eros: Yes indeed, now runs just fine. Many, many thanks.
George
gddeluca
20-05-2013, 20:41
Eros: Sorry to keep popping back in here. I think there is a problem in thinBasic cleanup when running embedded. I haven't got a repeatable example (yet) that I can provide, but I've seen instances where a small test macro runs and does a MSGBOX to display the result of some function. Then a different small test macro is run doing a similar small test and MSGBOX display. And the 2nd run, after its normal termination, ends up doing the MSGBOX display from the 1st macro's execution. !! ?? There have been other 'weirdnesses' happening, but this was the most obvious and identifiable.
My main App does call
CALL DWORD hProc_thinBasic_Release USING thinBasic_Release(0& _ 'Will be used in future release
) TO lRet after each RUN.
Any thoughts?
George
ErosOlmi
20-05-2013, 21:59
Hi George,
can you please tell me what's inside the message box?
Thanks
Eros
gddeluca
20-05-2013, 22:48
Eros: The extraneous MSGBOX that appears looks exactly like it did when the first macro executed. Same text exactly, so it looks like the thinBasic variables passed to the MSGBOX function are still around. It almost seems as if the thinBasic program and variable pool are still in existence and have somehow been 'merged' (if that's the right word) with the 2nd macro invocation.
The macros in question did not terminate with a STOP, they were simple 3-4 line test scripts. Maybe that's a clue? Execution 'falling into' old text storage? I've subsequently made sure a STOP is inserted as the last line passed to RUN, but since this is an intermittent problem, I'm not sure if that has had any effect. (yet) I thought I'd bring it up with you as it certainly looks like old data from a RUN execution is still in existence somewhere.
George
ReneMiner
20-07-2021, 07:10
Thats an old thread. But it provides the required information on its first page. May i introduce the Ring-language here?
Probably merits a thread of its own.
Its a cross-platform language- interpreter ,
i just make it quick:
It can embed itself. Or embed thinBasic. Or thinbasic can embed it. or embed it twice or trice -
It has no "end function", no case sensitivity, no end of possibilities,
It comes with plenty of features, runs in any environment from desktop-console, Windows-UI, 2D, 3D, as web-app or on mobile phones.
It knows only 1 numeric variable: number
Strings yes, literal or binary memory content
arrays? 1-based lists.
check it out here: https://ring-lang.github.io/
download there: https://sourceforge.net/projects/ring-lang/
__________________________________________________________________________________
As a precaution have a look at this:
1.ThinBASIC Language > thinBasic Functions > Application functions > APP_MutexCreate (https://www.thinbasic.com/public/products/thinBasic/help/html/app_mutexcreate.htm?zoom_highlightsub=mutex)
2.ThinBASIC Language > thinBasic Functions > Application functions > APP_MutexClose (https://www.thinbasic.com/public/products/thinBasic/help/html/app_mutexclose.htm?zoom_highlightsub=mutex)
3.What's new > 2007 - version history > Version 1.5.0.0 (https://www.thinbasic.com/public/products/thinBasic/help/html/version_1_5_0_0.htm?zoom_highlightsub=mutex)
Even if sharing memory is possible between different threads of a process - make sure not to access it at same time.
ReneMiner
25-07-2021, 22:56
...
Probably merits a thread of its own.
...
Probably not. Even we obtained our decimal system and the digits from arab roots and they have great mathematicians - the Ring lacks impermeableness, not really codetight and it feels a bit strange to use a verb as "see" as command to print.
If "show" were used instead it would make sense. The arab phrase for "Look at that!" might be the same as "Let me show you this..." or "Do you see it?"
Especially i see - when i watch my taskmanager -
multithreading out of control -
before actually a second thread is invoked 3 or 4 threads already yall'a-yall'a and nothing that could pull the brakes
Thank you ReneMiner for referring to Ring language. i am still testing it.
we can use the classic "print" by loading first "stdlib.ring" this is like uses "console"
load "stdlib.ring"
print("hello worlds")
or we can use "?" without loading stdlib.ring
regrading the keywords : see,give,ok and so on we can use the function ChangeRingKeyword
such as
ChangeRingKeyword see throw
will use throw for output
and
ChangeRingKeyword ok EndOfConditional
will use EndOfConditional for end of condition
some international users are using their own Unicode words instead of the original names
the following example from
https://www.codeproject.com/Articles/1089887/The-Ring-Programming-Language
ChangeRingKeyword see throw
ChangeRingKeyword ok EndOfConditional
for x = 1 to 10
for y = 1 to 10
throw "x=" + x + " y=" + y + nl
if x = 3 and y = 5
exit 2 # exit from 2 loops
EndOfConditional
next
next
but its first index is 1 (like thinbasic arrays)