Injecting c# type into Ironpython - c#

Right now I can use following code to access my c# types in IronPython as follow
import clr
clr.AddReference('myDLL.dll')
import myType
obj = myType()
however I don't want script developers to have clr.AddReference('myDLL.dll') line in Python source code, and inject myDLL.dll (and/or a c# class) directly from c# into ScriptEngine so the previous code will be something similar to:
import myType
obj = myType()
how can I achieve this?

You can solve this problem using following solution :
ScriptRuntime runtime = Python.CreateRuntime();
runtime.LoadAssembly(Assembly.GetAssembly(typeof(MyNameSpace.MyClass)));
ScriptEngine eng = runtime.GetEngine("py");
ScriptScope scope = eng.CreateScope();
ScriptSource src = eng.CreateScriptSourceFromString(MySource, SourceCodeKind.Statements);
var result = src.Execute(scope);
Now, in python script you can write:
from MyNameSpace import *
n=MyClass()
print n.DoSomeThing()

Related

C# code to Python with COM interface - casting issue

I have trouble to convert comtype in the needed objects. I get a working C# sample and must convert it into python Code. I use ComTypes for that.
The detailed Problem:
The Object Hirachy is the following(from the CANoe documentation):
System
+Namespaces:Namespaces (collection)
Namespaces
+Count
+Item:Namespace
Namespace
+Name
+Variables
+Namespaces:Namespaces
Python code:
App = CreateObject('CANoe.Application')
mNamespaces = App.System.Namespaces #oNamespaces = POINTER(INamespaces2)
mNamespace = mNamespaces.Item(3) #mNamespace = POINTER(INamespace), I have the Right object with a wrong interface. mNamespace had the right namespace object (_Statistics)
mStatisticsNamespaces = ? #here
C# excample Code to Transfer:
mSystem = (CANoe.System)mApplication.System;
mNamespaces = (CANoe.Namespaces)mSystem.Namespaces;
mNamespace = (CANoe.Namespace)mNamespaces["_Statistics"];
mStatisticsNamespaces = (CANoe.Namespaces)mNamespace.Namespaces;
mNamespaceCAN1 = (CANoe.Namespace)mStatisticsNamespaces["CAN1"];
mVariables = (CANoe.Variables)mNamespaceCAN1.Variables;
mVariable = (CANoe.Variable)mVariables["Busload"];
The mNamespace object contains now the Methods
mNamespace
+Name
+Variables
VisualStudio Variable view of mNamespace
VisualStudio Variable view of mNamespaces
It seams I must convert the mNamespace object like the C# sample. But I don't have an Idea how I can make it.
I had in Python no includes like c++/C# so I can't write like the C# sample.
Had anyone an Idee how to manage this?
Thanks

Remove Static references of Iron Python in wpf C# code

I use the DLLs IronPython.dll and IronPython.Wpf.dll for running Iron Python in C# code using ScriptEngine and ScriptScope
I am running Iron Python script from the WPF c# code as
public static ScriptEngine engine = Python.CreateEngine();
public static ScriptScope scope = engine.CreateScope();
ScriptSource source = engine.CreateScriptSourceFromFile(Path.Combine(currentPath, temp), Encoding.ASCII, SourceCodeKind.File);
source.Execute(scope);
The script in the Source file has several methods and could be called as
Func<object> func = scope.GetVariable("scriptMethodName");
func();
I found that even after closing the application, there is still some memory not released and found in the diagnostic tool the following item
IronPython.Runtime.CodeContext <0x2890FCC> [Static variable temp$2.$constant1]
The static variables of the IronPython runtime still hold some memory as given in https://github.com/IronLanguages/main/pull/1250. This actually causes many bigger objects to still stay in memory
Is there any fix for this ?
I tried the following, but no improvement in fixing this
I included the options dictionary to
Dictionary<string, object> options = new Dictionary<string, object>();
options["Debug"] = true;
options["LightweightScopes"] = true;
Also tried
engine.Runtime.Shutdown();
scope.Engine.Runtime.Shutdown();
This issue is causing heavy memory leak,Is there a possibility to get hold of the memory used by the mainwindow and clear it explicitly

No module named difflib

I want to execute python code from C# with following code.
static void Main(string[] args)
{
ScriptEngine engine = Python.CreateEngine();
ScriptSource source = engine.CreateScriptSourceFromFile(#"F:\Script\extracter.py");
source.Execute();
}
I have the problem at line source.Execute(), I got error "No module named difflib".
What is wrong in my code?
This is my python code (extracter.py).
import re
import itertools
import difflib
print "Hello"
This looks like your engine does not have access to Python standard library - it does not see difflib.py. Either fix the sys.path or copy difflib.py from Python 2.6 to f:\script folder.
re and itertools modules are written in C# and are part of IronPython.modules.dll - that's why importing them work.

Embedding IronPython in a C# application - import error on urllib

I have a Python file with as content:
import re
import urllib
class A(object):
def __init__(self, x):
self.x = x
def getVal(self):
return self.x
def __str__(self):
return "instance of A with value '%s'" % (self.getVal())
I also have a simple C# console project with the following code:
engine = Python.CreateEngine();
ScriptSource source = engine.CreateScriptSourceFromFile("test.py");
ScriptScope scope = engine.CreateScope();
ObjectOperations op = engine.Operations;
source.Execute(scope); // class object created
object klaz = scope.GetVariable("A"); // get the class object
object instance = op.Call(klaz, "blabla waarde"); // create the instance
object method = op.GetMember(instance, "getVal"); // get a method
string result = (string)op.Call(method); // call method and get result (9)
Console.WriteLine("Result: " + result); //output: 'Result: blabla waarde'
(I got this from this stackoverflow querstion and answer)
If I leave out the the import urllib statement in the Python file everything works fine. (meaning it finds the re module)
But as soon as i either add import urllib or import urllib2 I get the following exception:
ImportException was unhandled
No module named urllib
So somehow it can't find the urllib. I checked the IronPython lib folder and both urllib and urllib 2 are definitely there.
The same exception gets thrown when I import urllib in the C# code. (engine.ImportModule("urllib");)
Any ideas?
I'd like to manage the imports in the python code and not in the C# code.
(So I'd like to avoid stuff like this: engine.ImportModule("urllib");)
Edit:
Some extra info on what I'm actually going to use this for (maybe someone has an alternative):
I will have a main C# application and the python scripts will be used as extensions or plugins for the main application.
I'm using Python so that I don't need to compile any of the plugins.
I believe that 'Lib' being on sys.path from the interactive console is actually done inside ipy.exe - and when embedding you will have to add the path manually. Either the engine or the runtime has a 'SetSourcePaths' (or similar) method that will allow you to do this.
I face the same problem. Following "Tom E's" suggestion in the comments to fuzzyman's reply I could successfully resolve the issue. The issue seems to be it is not able resolve the location of the urllib.py. We need to set it.
You can check the following link for the question and answer.
The version of CPython you're importing from must match your IronPython version. Use CPython v2.5 for IronPython 2.0, or v2.6 for IronPython 2.6.
Try this:
import sys
sys.path.append(r'\c:\python26\lib') # adjust to whatever version of CPython you have installed.
import urllib

Simplfying DSL written for a C# app with IronPython

Thanks to suggestions from a previous question, I'm busy trying out IronPython, IronRuby and Boo to create a DSL for my C# app. Step one is IronPython, due to the larger user and knowledge base. If I can get something to work well here, I can just stop.
Here is my problem:
I want my IronPython script to have access to the functions in a class called Lib. Right now I can add the assembly to the IronPython runtime and import the class by executing the statement in the scope I created:
// load 'ScriptLib' assembly
Assembly libraryAssembly = Assembly.LoadFile(libraryPath);
_runtime.LoadAssembly(libraryAssembly);
// import 'Lib' class from 'ScriptLib'
ScriptSource imports = _engine.CreateScriptSourceFromString("from ScriptLib import Lib", SourceCodeKind.Statements);
imports.Execute(_scope);
// run .py script:
ScriptSource script = _engine.CreateScriptSourceFromFile(scriptPath);
script.Execute(_scope);
If I want to run Lib::PrintHello, which is just a hello world style statement, my Python script contains:
Lib.PrintHello()
or (if it's not static):
library = new Lib()
library.PrintHello()
How can I change my environment so that I can just have basic statments in the Python script like this:
PrintHello
TurnOnPower
VerifyFrequency
TurnOffPower
etc...
I want these scripts to be simple for a non-programmer to write. I don't want them to have to know what a class is or how it works. IronPython is really just there so that some basic operations like for, do, if, and a basic function definition don't require my writing a compiler for my DSL.
You should be able to do something like:
var objOps = _engine.Operations;
var lib = new Lib();
foreach (string memberName in objOps.GetMemberNames(lib)) {
_scope.SetVariable(memberName, objOps.GetMember(lib, memberName));
}
This will get all of the members from the lib objec and then inject them into the ScriptScope. This is done w/ the Python ObjectOperations class so that the members you get off will be Python members. So if you then do something similar w/ IronRuby the same code should basically work.

Categories