2015-10-16 13 views
7

I został zbudowany C# DLL (MyTestDll) przy użyciu pakietu Nuget UnmanagedExports:Ładowanie C# DLL z niezarządzani eksportu w Pythonie

[DllExport("Test", CallingConvention = CallingConvention.Cdecl)] 
public static string Test(string name) 
{ 
    return "hi " + name + "!"; 
} 

używam go od Pythona poprzez import ctypes DLL:

path = "C:\\Temp\\Test" 
os.chdir(path) 
dll = ctypes.WinDLL("MyTestDll.dll") 
f = dll.Test 
f.restype = ctypes.c_char_p 
print f('qqq') 

To tylko fantazja, działa.

Następnie dodałam jeszcze jeden DLL (NoSenseDll):

namespace NoSenseDll 
{ 
    public class NoSenseClass 
    { 
     public static int Sum(int a, int b) 
     { 
      return a + b; 
     } 
    } 
} 

zacząłem używać tego NoSenseDll wdrożyć MyTestDll:

[DllExport("Test", CallingConvention = CallingConvention.Cdecl)] 
public static string Test(string name) 
{ 
    return NoSenseDll.NoSenseClass.Sum(4, 5).ToString(); 
} 

Niestety, to nie działa. Python mówi:

WindowsError: [Error -532462766] Windows Error 0xE043435 

Próbowałem dodać C:\\Temp\\Test do drogi, ale to nie pomogło.


Napisałem C++ testu:

#include "stdafx.h" 
#include "windows.h" 
#include <iostream> 
#include <string> 
#include "WinBase.h" 

typedef char*(__stdcall *f_funci)(const char*); 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    int t; 
    std::string s = "C:\\Temp\\Test\\MyTestDll.dll"; 
    HINSTANCE hGetProcIDDLL = LoadLibrary(std::wstring(s.begin(), s.end()).c_str()); 

    f_funci funci = (f_funci)GetProcAddress(hGetProcIDDLL, "Test"); 

    std::cout << "funci() returned " << funci(std::string("qqq").c_str()) << std::endl; 
    std::cin >> t; 
    return EXIT_SUCCESS; 
} 

To działa, jeśli druga DLL (NoSenseDll) znajduje się w tym samym folderze co plik wykonywalny C++. To nie działa, jeśli dodaję do katalogu PATH tylko katalog NoSenseDll.

+0

* Próbowałem dodać 'C: \\ Temp \\ Test' do ścieżki, ale to nie pomogło. * Czy naprawdę używasz podwójnych ukośników? Może to może być problem. Tylko zgaduję. – Palec

+0

Zrobiłem co w mojej mocy, aby edytować twoje pytania i odpowiedzi, aby było łatwiejsze do zrozumienia i naprawiłem NoSen * c * eDll na NoSen * s * eDll. Dziękujemy za wysiłek wkładany w te pytania i odpowiedzi! – Palec

Odpowiedz

4

Projekt rozwiązanie:

  1. Kopiowanie NoSenseDll do folderu Pythona, w moim przypadku %HOMEPATH%\Anaconda.
  2. Uruchom ponownie IPython/Spyder.

Ostateczne rozwiązanie:

static MyTestDllClass() // static constructor 
{ 
    AppDomain currentDomain = AppDomain.CurrentDomain; 
    currentDomain.AssemblyResolve += new ResolveEventHandler(LoadFromSameFolder); 
} 
static Assembly LoadFromSameFolder(object sender, ResolveEventArgs args) 
{ 
    string folderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); 
    string assemblyPath = Path.Combine(folderPath, new AssemblyName(args.Name).Name + ".dll"); 
    if (File.Exists(assemblyPath) == false) return null; 
    Assembly assembly = Assembly.LoadFrom(assemblyPath); 
    return assembly; 
} 

Ostatnia uwaga:

Jeśli nie można używać IronPython z powodu matplotlib lub pand,
jeśli nie można użyć python.net ze względu na IPython lub spyder,
jeśli nie chcesz używać COM Interop tylko dlatego,
i jesteś prawdziwy Chcę, aby C# i Python współpracowały, użyj powyższego rozwiązania i C# reflection.

+0

Czy możesz wskazać problemy z pythonnetu w ipython lub spyder? – denfromufa

2

Możesz również sprawdzić Costura.Fody.

To jest zadanie kompilacji, które doda twoje zależności jako zasoby do twojego zespołu, a nawet zaimplementuje inicjalizator modułów, aby załadować je w czasie wykonywania.

+0

czy możesz podać przykład dla tej sprawy? Czym różni się to od twojego niezarządzanego eksportu? – denfromufa

+1

Nadal będziesz używać mojego pakietu, ale w Costurze twoje zależności zostaną dodane jako zasoby do twojego zespołu. Costura dodaje haki, aby je załadować. –