1

Using Ironpython, I created a .dll from a .py file. It has classes and respective functions that I want to call to be used in c#. I created the .dll so that I can hide the source from the user.

Here is what I have tried:

    ScriptEngine engine = Python.CreateEngine();
    scope = engine.CreateScope();
    engine.Runtime.LoadAssembly(Assembly.LoadFile(fullPath2DLL));
    scope = engine.ImportModule("Simulation");

However, it cannot find "Simulation".

Also, I want to import the whole script at once so I can call whatever, whenever [Rather than the class 'Simulation'].

7
  • Do you have to load the .dll at run time? Can you not just add a reference from your C# project? Commented Sep 17, 2015 at 21:03
  • 1
    @ColinGrealy I do not believe it works that easily. Since this is a python script into a dll, I must use the ScriptEngine and ScriptScope to load these in to be used at run time. It is for a winform app. Commented Sep 17, 2015 at 21:05
  • Sorry, you're right. Looks like you can't actually do this. You'll have to load the .py scripts instead. Commented Sep 17, 2015 at 21:12
  • @ColinGrealy No worries. Yes the goal is to not have the .PY available to the user. I want to hide this. I have spent weeks on this and haven't found a working solution. Seems like no one has really done it? Commented Sep 17, 2015 at 21:15
  • From the IronPython documentation, it doesn't look like this is possible with a dll. ironpython.net/documentation/dotnet/dotnet.html#id86 If you really don't want the .py file available to the user, you could encrypt and rename it? Then just decrypt as you need it. Commented Sep 17, 2015 at 21:18

1 Answer 1

2

Many things could go wrong, so I'll just show you complete example which works. Let's take this python code that I grabbed in some example:

MyGlobal = 5

class Customer(object):
"""A customer of ABC Bank with a checking account. Customers have the
following properties:

Attributes:
    name: A string representing the customer's name.
    balance: A float tracking the current balance of the customer's account.
"""

def __init__(self, name, balance=0.0):
    """Return a Customer object whose name is *name* and starting
    balance is *balance*."""
    self.name = name
    self.balance = balance

def withdraw(self, amount):
    """Return the balance remaining after withdrawing *amount*
    dollars."""
    if amount > self.balance:
        raise RuntimeError('Amount greater than available balance.')
    self.balance -= amount
    return self.balance

def deposit(self, amount):
    """Return the balance remaining after depositing *amount*
    dollars."""
    self.balance += amount
    return self.balance

Now let's open ipy and compile that into dll with:

>>> import clr
>>> clr.CompileModules("path_to.dll", "path_to.py");

Now we have dll. As you see python code contains class definition, and our goal is to create instance of that class in C# and call some methods.

 public class Program {
    private static void Main(string[] args) {
        ScriptEngine engine = Python.CreateEngine();            
        engine.Runtime.LoadAssembly(Assembly.LoadFile(@"path_to.dll"));
        // note how scope is created. 
        // "test" is just the name of python file from which dll was compiled. 
        // "test.py" > module named "test"
        var scope = engine.Runtime.ImportModule("test");
        // fetching global is as easy as this
        int g = scope.GetVariable("MyGlobal");
        // writes 5
        Console.WriteLine(g);
        // how class type is grabbed
        var customerType = scope.GetVariable("Customer");
        // how class is created using constructor with name (note dynamic keyword also)
        dynamic customer = engine.Operations.CreateInstance(customerType, "Customer Name");
        // calling method on dynamic object
        var balance = customer.deposit(10.0m);
        // this outputs 10, as it should
        Console.WriteLine(balance);
        Console.ReadKey();
    }
}
Sign up to request clarification or add additional context in comments.

8 Comments

var scope = engine.Runtime.ImportModule("test"); what is test? Also I have a global variable that I would like to access. I was hoping to ImportModule ALL. Otherwise I am not too sure how to get that variable
Updated my answer. Note how code now grabs value of global, and explanation of what is "test" in code comments.
Ah OK, I didn't realize it would be able to extract that information. I will try this out now, thx!
It says 'No module named urllib2'. How do I attach ironpython to this?
Well I provided you with simple example how to do what you want to. First verify it works for you as is, and you understand how. Then, if your more complex example doesnt - provide its python code, otherwise I will be pointlessly guessing why it fails. As a wild guess of this type - try import urllib2 into the scope first
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.