Reputation: 701
Anyone can share a working example on how to call a simple C# library (actually its WPF) from python code? (I have tried using IronPython and had too much trouble with unsupported CPython library my python code is using so I thought of trying the other way around and calling my C# code from Python).
Here is the example I was playing with:
using System.Runtime.InteropServices;
using System.EnterpriseServices;
namespace DataViewerLibrary
{
public interface ISimpleProvider
{
[DispIdAttribute(0)]
void Start();
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class PlotData : ServicedComponent, ISimpleProvider
{
public void Start()
{
Plot plotter = new Plot();
plotter.ShowDialog();
}
}
}
Plotter is a WPF windows that plots an Ellipse
I don't know how to call this code from my python all. Any suggestions?
Upvotes: 63
Views: 126224
Reputation: 121
This project has been developed for that exact purpose - use C# classes in regular Python
https://github.com/pythonnet/pythonnet/wiki
All you need to do is to install either MSI or EGG into your CPython. PyDotnet is Python module, so the executable stays regular python.exe from your installation of Python or Anaconda. Supported both 32bit and 64bit.
Unlimited access to all C# classes, methods with output and ref parameters, generic classes and generic methods, extension methods, private members.
Overloaded assembly loader with customized mechanics for searching assemblies.
.NET runtime type information convertible to class object, which can be instantiated as any other class.
Special import mode designed especially for Python interactive shell, which allows you to discover available assemblies, namespaces, classes, methods, etc.
I'm waiting for feedback:)
Upvotes: 12
Reputation: 103
Michael Baker already gave the correct answer.
Here is a working example:
The C# ClassLibrary code:
(don't forget the public keyword and mind the namespace, it becomes the python module name)
namespace MyDotNetClassLib
{
public class Adder
{
public static int StaticAdd(int left, int right)
{
return left + right;
}
public int Add(int left, int right)
{
return left + right;
}
}
}
The output is produced as ".\MyDotNetClassLib\bin\Debug\net7.0\MyDotNetClassLib.dll"
The python file: ".\PythonApplication\PythonApplication.py"
append the path to the dll file
AddReference the assembly name (usually dll filename without .dll)
import the module (which is the C# namespace)
import clr
from System import Console
#from System import String
#from System.Collections import *
import sys
sys.path.append('../MyDotNetClassLib/bin/Debug/net7.0/')
clr.AddReference("MyDotNetClassLib")
from MyDotNetClassLib import Adder
print()
print("hello from python")
Console.WriteLine("hello from C#")
print(f"My C# Adder static: {Adder.StaticAdd(1,2)}")
adder = Adder()
print(f"My C# Adder method: {adder.Add(3,4)}")
The Console output when called:
PS PythonApplication> python .\PythonApplication.py
hello from python
hello from C#
My C# Adder static: 3
My C# Adder method: 7
Compiled and run with:
Upvotes: 4
Reputation: 1204
Python for .Net (pythonnet) may be a reasonable alternative to IronPython in your situation. https://github.com/pythonnet/pythonnet/blob/master/README.rst
From the site:
Note that this package does not implement Python as a first-class CLR language - it does not produce managed code (IL) from Python code. Rather, it is an integration of the CPython engine with the .NET runtime. This approach allows you to use use CLR services and continue to use existing Python code and C-based extensions while maintaining native execution speeds for Python code.
Also
Python for .NET uses the PYTHONPATH (sys.path) to look for assemblies to load, in addition to the usual application base and the GAC. To ensure that you can implicitly import an assembly, put the directory containing the assembly in sys.path.
This package still requires that you have a local CPython runtime on your machine. See the full Readme for more info https://github.com/pythonnet/pythonnet
Upvotes: 18
Reputation: 997
It is actually pretty easy. Just use NuGet to add the "UnmanagedExports" package to your .Net project. See https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports for details.
You can then export directly, without having to do a COM layer. Here is the sample C# code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using RGiesecke.DllExport;
class Test
{
[DllExport("add", CallingConvention = CallingConvention.Cdecl)]
public static int TestExport(int left, int right)
{
return left + right;
}
}
You can then load the dll and call the exposed methods in Python (works for 2.7)
import ctypes
a = ctypes.cdll.LoadLibrary(source)
a.add(3, 5)
Upvotes: 51
Reputation: 3434
Since your post is tagged IronPython, if you want to use the sample C# the following should work.
import clr
clr.AddReference('assembly name here')
from DataViewerLibrary import PlotData
p = PlotData()
p.Start()
Upvotes: 24