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

Michael Foord fuzzyman at voidspace.org.uk
Tue Jun 16 02:17:03 CEST 2009


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
>   


-- 
http://www.ironpythoninaction.com/
http://www.voidspace.org.uk/blog





More information about the Ironpython-users mailing list