2015-10-16 85 views
7

我使用NuGet包UnmanagedExports建一個C#DLL(MyTestDll):加載C#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') 

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

我通過ctypes的DLL導入使用它在Python

這只是一個幻想,它的作品。

然後,我增加了一個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(); 
} 

不幸的是,這是行不通的。蟒蛇說:

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

我盡我所能編輯您的問答以便更容易理解,並且我將NoSen * c * eDll修正爲NoSen * s * eDll。感謝您爲此問答所做的努力! – 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; 
} 

最後一點:

如果你不能使用,因爲matplotlib或熊貓的IronPython的,
如果你不能使用python.net由於IPython或Spyder,
如果你不想使用COM Interop只是因爲,
和你真實希望讓C#和Python一起工作,使用上面的解決方案和C#反射。

+0

你能指點問題從pythonnet在ipython或spyder? – denfromufa

2

你也可以看看Costura.Fody。

這是一個構建任務,將您的依賴關係作爲資源添加到您的程序集,甚至掛鉤模塊初始化程序以在運行時加載它們。

+0

你能舉個例子嗎?這與您的非託管出口有何不同? – denfromufa

+1

您仍然會使用我的軟件包,但是在Costura中,您的依賴項將作爲資源添加到您的程序集中。 Costura增加掛鉤從那裏裝載它們。 –