[IronPython] Embedding IronPython and calling python functions from C#

Patrick van der Willik patrick at toolmaker.nl
Tue Jun 16 02:37:41 CEST 2009


The OnConnect is in the autoexec.py yes. While this works perfectly for 
setting variables, how does this work when I want to set my callback 
functions? I have several helper functions which reside on the C# side 
of my application in objects which I cannot spawn from within my 
scripts(As they're of vital importance to actually start my application).

I actually thought the scope I created was shared. Is there a way to get 
this working, so I can update the global table

Is there a way so I can update the global scope?

Michael Foord wrote:
> Patrick van der Willik wrote:
>> I am in fact using the 2nd 'flavour':
>>                 string modInvoke = String.Format("import {0}\nfrom 
>> {0} import *\n", "autoexec");
>
> So OnConnect is defined in your autoexec.py module?
>
> In this case it is looking for x in the scope in which it is defined 
> *not* in the scope from which it is called (lexical scoping).
>
> You should make x another parameter - and perhaps in modInvoke create 
> a wrapper function that looks up x in its scope and passes it to 
> OnConnect.
>
> Michael
>
>>                                var source = 
>> engine.CreateScriptSourceFromString(modInvoke, 
>> SourceCodeKind.Statements);
>>                 CompiledCode cc = source.Compile();
>>                 cc.Execute(scope);
>>
>>                 // And bind our public delegates
>>                 OnConnect = scope.GetVariable<Func<User, 
>> bool>>("OnConnect");
>>                 OnDisconnect = scope.GetVariable<Func<User, 
>> bool>>("OnDisconnect");
>>                 OnDataRecv = scope.GetVariable<Func<User, string, 
>> bool>>("OnDataReceived");
>>                 OnPreLogin = scope.GetVariable<Func<User, 
>> bool>>("OnPreLogin");
>>                 OnLogin = scope.GetVariable<Func<User, 
>> bool>>("OnLogin");
>>
>>                 Func<string> test = new Func<string>(Test);
>>                 scope.SetVariable("x", 10);
>>                 scope.SetVariable("Test", test);
>>
>> And in a later piece of code, I just call the OnConnect(newUser) 
>> delegate(in my C# part). Perhaps interesting to know, the autoexec 
>> has an import clientconn and from clientconn import *.
>>
>> Is my assumption that should work correct or am I missing something?
>>
>> Patrick
>>
>> Dino Viehland wrote:
>>> What about the code which is actually running the code that "def 
>>> OnConnect" lives in?
>>>
>>> I would expect you have either:
>>>         engine.ExecuteFile(..., scope)
>>>
>>> or:
>>>
>>>
>>> code = engine.CreateScriptSource*(...)
>>> cc = code.Compile()
>>> cc.Execute(scope)
>>>
>>> or
>>>
>>> code = engine.CreateScriptSource*(...)
>>> code.Execute(scope)
>>>
>>> where scope in all of these would be the scope that you've populated 
>>> with the value of "x".
>>>
>>> I suspect the 2nd one is the one you want so that you can run the 
>>> same code against multiple
>>> scopes w/ different sets of bound variables based upon the current 
>>> request.
>>>
>>>
>>> -----Original Message-----
>>> From: users-bounces at lists.ironpython.com 
>>> [mailto:users-bounces at lists.ironpython.com] On Behalf Of Patrick van 
>>> der Willik
>>> Sent: Monday, June 15, 2009 4:26 PM
>>> To: Discussion of IronPython
>>> Subject: Re: [IronPython] Embedding IronPython and calling python 
>>> functions from C#
>>>
>>> The actual code that uses these variables from within a script looks
>>> like this:
>>> def OnConnect(user):
>>>     s = "The value of x: " + str(x)
>>>     user.Send(s, True)
>>>     user.Receiver = "user_username"
>>>     return True
>>>
>>> And the complete exception is:
>>> [ERROR] [16-6-2009 1:18:16] An error occured while attempting to accept
>>> a new connection. Error: name 'x' is not defined
>>> [ERROR] [16-6-2009 1:18:16] Stacktrace:    at
>>> IronPython.Runtime.PythonContext.MissingName(SymbolId name)
>>>    at Microsoft.Scripting.Runtime.ModuleGlobalWrapper.GetCachedValue()
>>>    at 
>>> Microsoft.Scripting.Runtime.ModuleGlobalWrapper.get_CurrentValue()
>>>    at S$2.OnConnect$6(Object user)
>>>    at _stub_$17##8(Closure , CallSite , Object , User )
>>>    at Microsoft.Scripting.Actions.MatchCaller.Call2[T0,T1,TRet](Func`4
>>> target, CallSite site, Object[] args)
>>>    at 
>>> Microsoft.Scripting.Actions.CallSite`1.UpdateAndExecute(Object[] args)
>>>    at
>>> Microsoft.Scripting.Actions.UpdateDelegates.Update2[T,T0,T1,TRet](CallSite 
>>>
>>> site, T0 arg0, T1 arg1)
>>>    at System.Boolean(User)(Object[] , User )
>>>    at TestProject.Users.ConnectionManager.AcceptNewConnnections() in
>>> C:\Users\Patrick\Documents\Visual Studio
>>> 2008\Projects\test\TestProject\Users\ConnectionManager.cs
>>> :line 108
>>>
>>> Weird thing is: If I use GetVariable, it works fine. The call is 
>>> done at
>>> a later location in the program that where I do the SetVariable, but 
>>> the
>>> script scope hasn't ben changed in the meantime.
>>>
>>> Patrick
>>>
>>> Michael Foord wrote:
>>>  
>>>> Patrick van der Willik wrote:
>>>>    
>>>>> Alright, that actually really worked pretty good, and I finally got
>>>>> it all working as it should. However, I'm running into 1 more little
>>>>> issue, now I need to go the other way around aswell. I have several
>>>>> functions marked in my application as PythonExportable. In a certain
>>>>> startup phase of the application, after creating the IronPython
>>>>> hosting environment, I walk over all these classes using Reflection,
>>>>> take the tagged functions and put these into my IP scope.
>>>>>
>>>>> However, my simple tests for some reason cause my SetVariable() calls
>>>>> to not work. I added 2 tests to my scripts, one where I add a
>>>>> variable into the scope and another one where I add a delegate.
>>>>> However, in both cases, whenever I use these variables from within my
>>>>> scripts, they don't seem to work. Code:
>>>>>                Func<string> test = new Func<string>(Test);
>>>>>                scope.SetVariable("x", 10);
>>>>>                scope.SetVariable("Test", test);
>>>>>
>>>>> Accessing them in my scripts have the effect of triggering an
>>>>> exception that shows that x is undefined.
>>>>>       
>>>> Can you show the actual code that attempts to use them and the actual
>>>> exception message raised.
>>>>
>>>> Michael
>>>>
>>>>    
>>>>> Some insights into this would be of great help.
>>>>>
>>>>> Patrick
>>>>>
>>>>> Michael Foord wrote:
>>>>>      
>>>>>> See this section of my hosting article:
>>>>>>
>>>>>> http://www.voidspace.org.uk/ironpython/hosting_api.shtml#functions-as-delegates 
>>>>>>
>>>>>>
>>>>>>
>>>>>> You cast the function to a delegate as you fetch it out of the 
>>>>>> scope.
>>>>>>
>>>>>> Michael
>>>>>>
>>>>>> Patrick van der Willik wrote:
>>>>>>        
>>>>>>> I'm a bit late with responding to this as I was kinda busy. I used
>>>>>>> the code that was given Stephen and it seems to run properly
>>>>>>> without throwing exceptions. However, I created a little
>>>>>>> autoexec.py file with a simple function in it with 2 parameters.
>>>>>>>
>>>>>>> The main problem here is: How do I call the function through the
>>>>>>> scope? I used engine.CreateScope() to create myself a new scope,
>>>>>>> but from there on, I'm basically lost(again). What I basically want
>>>>>>> to do, is call my function 'add' with 2 parameters(say, 10 and 15).
>>>>>>> The modules itself are loaded into a ScriptSource.
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Patrick
>>>>>>>
>>>>>>> Lepisto, Stephen P wrote:
>>>>>>>          
>>>>>>>> What I do when I want to work with python modules from embedded
>>>>>>>> IronPython is set the IronPython search path with the path of the
>>>>>>>> module to load then  create and execute a small python script that
>>>>>>>> loads the main python modules into the current scope.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> string moduleName = Path.GetFileName(modulePath);
>>>>>>>>
>>>>>>>> string path = Path.GetDirectoryName(modulePath);
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> ICollection<string> paths = _pythonEngine.GetSearchPaths();
>>>>>>>>
>>>>>>>> if (!paths.Contains(path))
>>>>>>>>
>>>>>>>> {
>>>>>>>>
>>>>>>>>     paths.Add(path);
>>>>>>>>
>>>>>>>>     _pythonEngine.SetSearchPaths(paths);
>>>>>>>>
>>>>>>>> }
>>>>>>>>
>>>>>>>> string modInvoke = String.Format("import {0}\nfrom {0} import
>>>>>>>> *\n", moduleName);
>>>>>>>>
>>>>>>>> ScriptSource source =
>>>>>>>> _pythonEngine.CreateScriptSourceFromString(modInvoke,
>>>>>>>>
>>>>>>>>
>>>>>>>> Microsoft.Scripting.SourceCodeKind.Statements);
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> Where modulePath is the full path to the python module or package
>>>>>>>> to load.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> I can then invoke methods or access attributes using the
>>>>>>>> IronPython scope.  In this way, I can interact with the python
>>>>>>>> modules for as long as necessary before closing down the
>>>>>>>> scope/engine.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> *From:* users-bounces at lists.ironpython.com
>>>>>>>> [mailto:users-bounces at lists.ironpython.com] *On Behalf Of *Dody
>>>>>>>> Gunawinata
>>>>>>>> *Sent:* Thursday, June 11, 2009 9:09 AM
>>>>>>>> *To:* Discussion of IronPython
>>>>>>>> *Subject:* Re: [IronPython] Embedding IronPython and calling
>>>>>>>> python functions from C#
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> You can read all yours file scripts, then using StringBuilder to
>>>>>>>> combine then and call CreateScriptSourceFromString()
>>>>>>>>
>>>>>>>> Then you can call your functions within the combined scripts
>>>>>>>> normally. Pretty much you are creating a giant source code on the
>>>>>>>> fly.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On Thu, Jun 11, 2009 at 5:32 PM, Patrick van der Willik
>>>>>>>> <patrick at toolmaker.nl <mailto:patrick at toolmaker.nl>> wrote:
>>>>>>>>
>>>>>>>> I'm currently attempting to embed the IronPython 2 runtimes into
>>>>>>>> an existing application written in C#. However, I find the amount
>>>>>>>> of documentation lacking on what I'm trying to do. I currently
>>>>>>>> have a proof-of-concept version which uses Lua and LuaInterface,
>>>>>>>> but the people who have to write the scripts dislike Lua(Well,
>>>>>>>> more hate it with a passion) and would love to see this working
>>>>>>>> with Python.
>>>>>>>>
>>>>>>>> My host application is a networked application that must trigger
>>>>>>>> certain scripts functions on events generated by the connected
>>>>>>>> clients. The idea is that when my application starts, it will load
>>>>>>>> the IronPython script environment, launches an 'autoexec.py' which
>>>>>>>> will load various other scripts files and do some housekeeping.
>>>>>>>> Once this all is completed, it will start listening to incoming
>>>>>>>> connections. However, in various scenarios, the application has to
>>>>>>>> trigger scripted functions when data is received from a client.
>>>>>>>> Which script function is called is different per client and per
>>>>>>>> event. I have events for connecting, logging on, disconnecting and
>>>>>>>> a set of data specific events after receiving data. This highly
>>>>>>>> depends on the received packets.
>>>>>>>>
>>>>>>>> My question here is: How do I embed IronPython in such a fashion
>>>>>>>> that I can load my scripts and then trigger various functions
>>>>>>>> within that? I've seen many examples that just call
>>>>>>>> CreateScriptSourceFromString() or File each time in which just 1
>>>>>>>> piece of code is implemented. This is not suitable for the needs
>>>>>>>> here because the scripted systems can become quite complex.
>>>>>>>>
>>>>>>>> With regards,
>>>>>>>> Patrick
>>>>>>>>
>>>>>>>>
>>>>>>>> _______________________________________________
>>>>>>>> Users mailing list
>>>>>>>> Users at lists.ironpython.com <mailto:Users at lists.ironpython.com>
>>>>>>>> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> -- 
>>>>>>>> nomadlife.org <http://nomadlife.org>
>>>>>>>>
>>>>>>>> ------------------------------------------------------------------------ 
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> _______________________________________________
>>>>>>>> Users mailing list
>>>>>>>> Users at lists.ironpython.com
>>>>>>>> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>>>>>>>>
>>>>>>>>             
>>>>>>> ------------------------------------------------------------------------ 
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> _______________________________________________
>>>>>>> Users mailing list
>>>>>>> Users at lists.ironpython.com
>>>>>>> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>>>>>>>
>>>>>>>           
>>>>>>         
>>>>> _______________________________________________
>>>>> Users mailing list
>>>>> Users at lists.ironpython.com
>>>>> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>>>>>       
>>>>     
>>>
>>> _______________________________________________
>>> Users mailing list
>>> Users at lists.ironpython.com
>>> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>>> _______________________________________________
>>> Users mailing list
>>> Users at lists.ironpython.com
>>> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>>>
>>>   
>>
>> ------------------------------------------------------------------------
>>
>> _______________________________________________
>> Users mailing list
>> Users at lists.ironpython.com
>> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>>   
>
>




More information about the Ironpython-users mailing list