2011-09-09 27 views
31

Chiunque può condividere un esempio funzionante su come chiamare una semplice libreria C# (in realtà il suo WPF) dal codice Python? (Ho provato a usare IronPython e ho avuto troppi problemi con la libreria CPython non supportata che il mio codice Python sta usando, quindi ho pensato di provare il contrario e di chiamare il mio codice C# da Python).Chiamare una libreria C# da python

Ecco l'esempio stavo giocando con:

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 è un Windows WPF che traccia un'ellisse

non so come chiamare questo codice dal mio python tutti. Eventuali suggerimenti?

+0

È possibile utilizzare un C++/Wrapper CLI. Vedi http://stackoverflow.com/a/42930903/1178267 come risposta di riferimento – anhoppe

risposta

2

Non sono un esperto .NET, ma il codice sembra come se il metodo fosse esposto come oggetto COM. Quindi puoi provare il pacchetto http://starship.python.net/crew/mhammond/win32/ per accedervi.

+0

È * possibile * esporre gli oggetti .NET come oggetti COM, ma c'è un impatto sulle prestazioni e non è l'impostazione predefinita. - Inoltre se lo fai male può portare a perdite di memoria. - Generalmente utilizzeresti questo approccio solo per la retrocompatibilità, come se si stesse integrando con una tecnologia precedente che già supporta COM. - Inoltre, è ovvio che se segui questo approccio sei completamente limitato alla piattaforma Windows. – BrainSlugs83

10

Python per .Net (pythonnet) può essere una ragionevole alternativa a IronPython nella tua situazione. https://github.com/pythonnet/pythonnet/blob/master/README.md

Dal sito:

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.

anche

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.

Questo pacchetto richiede ancora che si dispone di un runtime CPython locale sulla propria macchina. Vedere il Readme completo per ulteriori informazioni http://pythonnet.github.io/readme.html

12

Poiché il tuo post è codificato IronPython, se si desidera utilizzare l'esempio C#, dovrebbe funzionare.

import clr 
clr.AddReference('assembly name here') 
from DataViewerLibrary import PlotData 

p = PlotData() 
p.Start() 
+3

Lo stesso identico codice funziona con le ultime versioni di Python per .Net. È bello sapere che entrambe le soluzioni (IronPython e CPython + PythonNet) funzionano allo stesso modo. – Vincent

27

In realtà è piuttosto semplice. Basta usare NuGet per aggiungere il pacchetto "UnmanagedExports" al tuo progetto .Net. Vedi https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports per i dettagli.

È quindi possibile esportare direttamente, senza dover fare un livello COM. Ecco l'esempio di codice C#:

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; 
    } 
} 

È quindi possibile caricare la DLL e chiamare i metodi esposti in Python (che funziona per 2,7)

import ctypes 
a = ctypes.cdll.LoadLibrary(source) 
a.add(3, 5) 
+0

Molto bello se hai il controllo della biblioteca. Altrimenti immagino che tu possa creare un wrapper .dll con le convenzioni di chiamata in stile C. – CodeMonkey

+2

Ho ricevuto l'errore successivo: AttributeError: funzione 'add' non trovata – constructor

+3

vedi nota importante: http://stackoverflow.com/questions/34417972/no-functions-in-c-sharp-dll-with-rgiesecke-dllexport – constructor

7

Questo progetto è stato sviluppato per questo scopo esatto - uso C# in Python le classi regolari

https://bitbucket.org/pydotnet/pydotnet/wiki/Home

Tutto quello che dovete fare è installare sia MSI o UOVO nella vostra CPython. PyDotnet è un modulo Python, quindi l'eseguibile rimane regolarmente python.exe dall'installazione di Python o Anaconda. Supportato sia a 32 bit che a 64 bit.

Accesso illimitato a tutte le classi C#, metodi con parametri di output e ref, classi generiche e metodi generici, metodi di estensione, membri privati.

Caricatore di gruppo sovraccarico con meccanica personalizzata per la ricerca di assiemi.

Informazioni sul tipo di runtime .NET convertibili in oggetti di classe, che possono essere istanziati come qualsiasi altra classe.

modalità di importazione appositamente progettata soprattutto per Python shell interattiva, che permette di scoprire le assemblee disponibili, i namespace, classi, metodi, ecc

Sono in attesa di un feedback :)

+0

> >> import dotnet.seamless Traceback (ultima chiamata ultima): File "", riga 1, in File "C: \ Programmi \ Python35-32 \ lib \ site-packages \ dotnet \ __ init__.py ", la linea 21, in importazione dotnet.moduleloader file "C: \ Program Files \ Python35-32 \ lib \ site-packages \ dotnet \ moduleloader.py", la linea 24, in da dotnet importazione PyDotnet come _dotnet ImportError: caricamento DLL non riuscito: il modulo specificato co non potrebbe essere trovato –