2015-10-16 13 views
7

tôi đã xây dựng một C# DLL (MyTestDll) bằng cách sử dụng gói NuGet UnmanagedExports:tải C# DLL với kim ngạch xuất khẩu không được quản lý vào Python

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

tôi sử dụng nó từ Python qua nhập khẩu 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') 

Nó chỉ là một tưởng tượng, nó hoạt động.

Sau đó, tôi đã thêm một DLL hơn (NoSenseDll):

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

tôi bắt đầu sử dụng NoSenseDll này để thực hiện MyTestDll:

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

Thật không may, nó không hoạt động. Python nói:

WindowsError: [Error -532462766] Windows Error 0xE043435 

Tôi đã cố thêm C:\\Temp\\Test vào đường dẫn, nhưng điều đó không có tác dụng.


Tôi đã viết một bài kiểm tra ++ 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; 
} 

Nó hoạt động nếu DLL thứ hai (NoSenseDll) là trong thư mục giống như ++ thực thi C. Nó không hoạt động nếu tôi chỉ thêm thư mục NoSenseDll vào PATH.

+0

* Tôi đã cố gắng thêm 'C: \\ Temp \\ Test' vào đường dẫn, nhưng điều đó không có ích. * Bạn có thực sự sử dụng dấu gạch chéo ngược kép không? Có lẽ đó có thể là vấn đề. Chỉ cần đoán thôi. – Palec

+0

Tôi đã cố gắng hết sức để chỉnh sửa Giải Đáp của bạn để dễ hiểu hơn, và tôi đã sửa NoSen * c * eDll thành NoSen * s * eDll. Cảm ơn những nỗ lực bạn đưa vào phần Hỏi & đáp này! – Palec

Trả lời

4

Dự thảo giải pháp:

  1. Sao chép NoSenseDll vào thư mục của Python, trong trường hợp của tôi %HOMEPATH%\Anaconda.
  2. Khởi động lại IPython/Spyder.

giải pháp cuối cùng:

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

Cuối cùng lưu ý:

Nếu bạn không thể sử dụng IronPython vì matplotlib hay gấu trúc,
nếu bạn không thể sử dụng python.net vì IPython hoặc spyder,
nếu bạn không muốn sử dụng COM Interop chỉ vì,
và bạn thực ly muốn lấy C# và Python làm việc cùng nhau, sử dụng giải pháp trên và phản xạ C#.

+0

bạn có thể chỉ ra các vấn đề từ pythonnet trong ipython hoặc spyder không? – denfromufa

2

Bạn cũng có thể xem Costura.Fody.

Đây là nhiệm vụ xây dựng sẽ bổ sung các phụ thuộc của bạn làm tài nguyên cho hội đồng của bạn và thậm chí gắn một trình khởi tạo mô-đun để tải chúng khi chạy.

+0

bạn có thể cung cấp ví dụ cho trường hợp này không? Làm thế nào khác là điều này từ bạn xuất khẩu không quản lý? – denfromufa

+1

Bạn vẫn muốn sử dụng gói của tôi, nhưng với Costura, phụ thuộc của bạn sẽ được thêm vào dưới dạng tài nguyên trong assembly của bạn. Costura thêm móc để tải chúng từ đó. –

Các vấn đề liên quan