Sign in to follow this  
Followers 0
Michiel

A function inside an included script calling a function inside the main script

15 posts in this topic

I'm trying to partition my program into libraries, but what I do need is for functions inside those libraries to log their output to one file or one specific control. But when I'm writing and testing au3 libraries to be included by the main program, SciTE doesn't know that the functions called, such as gLog() will be present in the main program.

So what I'm asking is: is there an elegant way to call functions inside the main program from inside an included library? If I'm supposed to pass a reference to the library, then where should I be doing that? I can't do it immediately when I'm running #include "..."  can I? Or, am I going about this the wrong way entirely? If so, how do I realize a centralized logging facility where I can have all units writing to one file or dialog of my choosing? :D

Share this post


Link to post
Share on other sites



I think some clarification would be helpful (maybe some code too).  When you use #include you are including the entire "library" in your main program.  It is similar to just having written a large program.  If you use your includes at the top of your main program then all the functions and variables will be present as the main the program runs.  You can also pass messages to a log file or a GUI (hidden or visible).  I am not sure what you mean by "all units".  Can you explain in a bit more detail? 


Build your own poker game with AutoIt: pokerlogic.au3 | Learn To Program Using FREE Tools with AutoIt

Share this post


Link to post
Share on other sites

Meanwhile, I've started setting it up with a 'log' unit, so maybe I've got it solved for now.

Try to picture it like this:

MAIN.au3

UNIT #1.au3

UNIT #2.au3

UNIT #3.au3

 

Like all developers, I want to split off a program into units. I want those units to be able to log warnings and other messages to one main window control. Currently I use an edit control for that. Above you see my 'main' script including 'units'.

Now, of course, MAIN.au3 can call any function in any UNIT.au3. But can a UNIT call a function in MAIN.au3?

Right now, after my first post in this thread, I've begun writing a log.au3 with '#include-once' and with an init function that sets a local unit-wide variable to an edit control, so for now, the bases seem covered. I was just wondering what else is possible, and if, for example, it is possible to call functions in MAIN from one of those UNIT scripts you see above.

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

The includes can call other functions just like it was part of one big script.  Example:

; main script
#include<funcincludetest.au3>
func _hello()
    MsgBox("","","hello")
EndFunc

Then this is the include:

;func include test file
func _callHello()
    _hello()
EndFunc
_callHello()

So the above included script is calling the function from the main script.  Does that answer your question?

Edited by Jfish

Build your own poker game with AutoIt: pokerlogic.au3 | Learn To Program Using FREE Tools with AutoIt

Share this post


Link to post
Share on other sites

Michiel,

I would take a different approach.

You want the various #include files to use a common logging process which will display using a control in the main script. Why not put all the logging functions into another #include file which will be included by all of the other UNIT #include files? (Of course you would need to use #include-once within the logging library to prevent multiple inclusions) That way all of the UNIT files can call the logging functions without problem. Inside the logging library you would have an Initiate function through which you identify the control used in the main script to display the log entries - if this control is not initialised then no logging happens, but there will be no errors either.

Here is a short example:

#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>

;######################################################
; This is the included logging library
#include-once
#include <GuiEdit.au3>

Global $iLog_Control = 0

; This function initialises the logging process
Func _Log_Init($iControl)
    If $iControl Then $iLog_Control = $iControl
EndFunc

Func _Log_Write($sText)
    If $iLog_Control Then
        ; Logging has been initiated
        _GUICtrlEdit_AppendText($iLog_Control, $sText & @CRLF)
    Else
        ; Or else show the problem
        MsgBox($MB_SYSTEMMODAL, "Error", "Logging not initiated")
    EndIf
EndFunc
;#######################################################

;#######################################################
; This is one of the UNIT includes

; Include the logging library - of course here the code is already included above
; #include "Logging.au3"

; Start a logging process
AdlibRegister("_UNIT_Logger", 2000) ; Comment this line to see what happens if the edit is not initialised <<<<

Func _UNIT_Logger()
    _Log_Write("UNIT log @ " & @SEC)
EndFunc
;#######################################################

; Now the main script

; Include the UNIT include - of course here the code is already included above
; #include "UNIT.au3"

$hGUI = GUICreate("Test", 500, 500)

$cEdit = GUICtrlCreateEdit("", 10, 10, 200, 400)

GUISetState()

; Initialise the edit control for logging
_Log_Init($cEdit)

; And watch the log fill.......

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd
Please ask if you have any questions. :)

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

To offer yet another opinion... :)

Call me old school, but I think logging for a distributed application (as this sounds like it will be), especially one that has a number of modules to it, should take place in the Windows Event Viewer. You will only help anyone trying to troubleshoot your application down the road by using clear and concise Event Viewer reporting.


√-1 2^3 ∑ π, and it was delicious!

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

The includes can call other functions just like it was part of one big script.  Example:

; main script
#include<funcincludetest.au3>
func _hello()
    MsgBox("","","hello")
EndFunc
Then this is the include:

;func include test file
func _callHello()
    _hello()
EndFunc
_callHello()
So the above included script is calling the function from the main script.  Does that answer your question?

 

 

Yeah, I sort of had it like that, but unfortunately when I do Tools->SyntaxCheck Prod , SciTE gives me errors because _hello() isn't declared in the unit calling it. Of course, I can live with that and ignore it, but, as the script grows, so will the number of instances of this happening until it all eventually becomes impossible to error check the lot. :ermm:

 

So, if only I had a syntactically sound and accepted way of doing this that would be acceptable to my IDE's error checking mechanisms. :shifty:

 

 

 

<snip>

Here is a short example:

#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>

;######################################################
; This is the included logging library
#include-once
#include <GuiEdit.au3>

Global $iLog_Control = 0

; This function initialises the logging process
Func _Log_Init($iControl)
    If $iControl Then $iLog_Control = $iControl
EndFunc

Func _Log_Write($sText)
    If $iLog_Control Then
        ; Logging has been initiated
        _GUICtrlEdit_AppendText($iLog_Control, $sText & @CRLF)
    Else
        ; Or else show the problem
        MsgBox($MB_SYSTEMMODAL, "Error", "Logging not initiated")
    EndIf
EndFunc
;#######################################################

;#######################################################
; This is one of the UNIT includes

; Include the logging library - of course here the code is already included above
; #include "Logging.au3"

; Start a logging process
AdlibRegister("_UNIT_Logger", 2000) ; Comment this line to see what happens if the edit is not initialised <<<<

Func _UNIT_Logger()
    _Log_Write("UNIT log @ " & @SEC)
EndFunc
;#######################################################

; Now the main script

; Include the UNIT include - of course here the code is already included above
; #include "UNIT.au3"

$hGUI = GUICreate("Test", 500, 500)

$cEdit = GUICtrlCreateEdit("", 10, 10, 200, 400)

GUISetState()

; Initialise the edit control for logging
_Log_Init($cEdit)

; And watch the log fill.......

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

 

Well, wouldn't you know it, that's exactly what I did down almost to the function names! (i.e. I made a logInit() , which writes a unit-local variable with the handle to the edit control!) :thumbsup:

 

Edited by Michiel

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

If you are calling a function within included scripts, then that function (logically) should be in that script file, or another included script...like a script that contains your logging functions.

Your primary driving script should then include all the above.

You should be able to execute any given 'included' script, and not get scite validation errors, or you are not doing everything you should be.

Edited by jdelaney

IEbyXPATH-Grab IE DOM objects by XPATH IEscriptRecord-Makings of an IE script recorder ExcelFromXML-Create Excel docs without excel installed GetAllWindowControls-Output all control data on a given window.

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

You should be able to execute any given 'included' script, and not get scite validation errors, or you are not doing everything you should be.

 

Quoting someone else's code:

The includes can call other functions just like it was part of one big script.  Example:

; main script
#include<funcincludetest.au3>
func _hello()
    MsgBox("","","hello")
EndFunc

Then this is the include:

;func include test file
func _callHello()
    _hello()
EndFunc
_callHello()

So the above included script is calling the function from the main script.  Does that answer your question?

 

Tools->SyntaxCheck Prod, if run on the include, will then error on _hello() in the include, will it not?

Or does it work for you?

Edited by Michiel

Share this post


Link to post
Share on other sites

Nope, that would blow up without the #include back to the main script.

If an included script is calling a function, then it shouldn't be in the 'main' script...I think of 'main' scripts as something that drives exectuion of functions in other libraries.

Personal preference...I don't want to have to include other 'main' scripts in new 'main' scripts.


IEbyXPATH-Grab IE DOM objects by XPATH IEscriptRecord-Makings of an IE script recorder ExcelFromXML-Create Excel docs without excel installed GetAllWindowControls-Output all control data on a given window.

Share this post


Link to post
Share on other sites

Personal preference...I don't want to have to include other 'main' scripts in new 'main' scripts.

 

Yeah, that makes a lot of sense to me too...

Share this post


Link to post
Share on other sites

Just to weigh back in here ... I agree with all the comments about the better approaches (from far more skilled coders than myself).  I was merely demonstrating that you could call a function in the main script from an included script though it may not be best practices to do so. 

 

Now, of course, MAIN.au3 can call any function in any UNIT.au3. But can a UNIT call a function in MAIN.au3?


Build your own poker game with AutoIt: pokerlogic.au3 | Learn To Program Using FREE Tools with AutoIt

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

It appears to work.

Main.au3 ==> run this script.

; #include-once
#include 'include2.au3'

_2()

Func _1()
    Msgbox(0, "", "Hello World")
EndFunc

;

include2.au3

Func _2()
    _1()
EndFunc

;

You must run Main.au3. This includes the second library which then calls the first library and bingo. It's a very disorganized mess and it's easy to write code which is unstable when your libraries are like that. As Melba showed earlier, you really ought to create a shared function library which you can call from either a main script or another library - providing you use #include-once where appropriate.

BTW I didn't run the code using SciTE. I would expect an error if I had attempted that.

Edited by czardas

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

I ran mine in Scite without an error.  Mine was a bit different because I just had the included script call a function in the main script without first being called (that just sounds confusing typing it).

+>07:36:56 AU3Check ended.rc:0
+>07:36:56 AutoIt3Wrapper Finished.
>Exit code: 0    Time: 0.4385
Edited by Jfish

Build your own poker game with AutoIt: pokerlogic.au3 | Learn To Program Using FREE Tools with AutoIt

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

It is slightly surprising that it works. I was thinking along the same lines as jdelaney. It changes my understanding of how the interpreter actually works. Even so, it's still very easy to mess up as in the following bad example.

;

Main.au3 ==> WARNING <== Code is unstable.

#include 'include2.au3'

Global $sGlobalString = "Hello World"

Func _1()
    Msgbox(0, "", $sGlobalString)
EndFunc

;

include2.au3

_1()
Edited by czardas

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0