2015-10-16 7 views
7

Я построил C# DLL (MyTestDll) с использованием пакета NuGet UnmanagedExports:Загрузка C# DLL с неуправляемыми экспорта в Python

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

я использую его из Python через импорт 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') 

Это просто фантазия, она работает.

Затем я добавил еще одну DLL (NoSenseDll):

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

Я начал использовать этот NoSenseDll реализовать MyTestDll:

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

К сожалению, это не работает. Python говорит:

WindowsError: [Error -532462766] Windows Error 0xE043435 

Я пытался добавить C:\\Temp\\Test на пути, но это не помогло.


Я написал тест на C++:

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

Это работает, если второй DLL (NoSenseDll) находится в той же папке, что и исполняемый файл C++. Это не работает, если я просто добавлю папку NoSenseDll в PATH.

+0

* Я попытался добавить 'C: \\ Temp \\ Test' в путь, но это не помогло. * Вы действительно использовали двойную обратную косую черту? Возможно, это может быть проблемой. Просто гадать. – Palec

+0

Я сделал все возможное, чтобы изменить Q & A, чтобы быть более понятным, и я исправил NoSen * c * eDll для NoSen * s * eDll. Спасибо за усилия, которые вы вложили в этот Q & A! – Palec

ответ

4

Проект решения:

  1. Копировать NoSenseDll в папку Python, в моем случае %HOMEPATH%\Anaconda.
  2. Перезапустите IPython/Spyder.

Окончательное решение:

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

Конечная нота:

Если вы не можете использовать IronPython из Matplotlib или панды,
, если вы не можете использовать python.net из-за IPython или spyder,
, если вы не хотите использовать COM Interop только потому, что
и вы действительно Я хочу, чтобы C# и Python работали вместе, используйте вышеприведенное решение и отражение C#.

+0

вы можете указать на проблемы с pythonnet в ipython или spyder? – denfromufa

2

Вы также можете проверить Costura.Fody.

Это задача сборки, которая добавит ваши зависимости в качестве ресурсов вашей сборки и даже подключит инициализатор модуля для их загрузки во время выполнения.

+0

Вы можете привести пример для этого случая? Насколько это отличается от вашего неуправляемого экспорта? – denfromufa

+1

Вы по-прежнему используете мой пакет, но с Costura ваши зависимости добавляются в качестве ресурсов в вашу сборку. Costura добавляет крючки, чтобы загрузить их оттуда. –

 Смежные вопросы

  • Нет связанных вопросов^_^