Downloading C # DLL with Unmanaged Export in Python

Ive built the C # DLL (MyTestDll) using the NuGet UnmanagedExports package:

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

I use it from Python through import of 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') 

This is just a fantasy, it works.

Then I added another DLL (NoSenseDll):

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

I started using this NoSenseDll to implement MyTestDll:

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

Unfortunately, it does not work. Python says:

 WindowsError: [Error -532462766] Windows Error 0xE043435 

Ive tried adding C:\\Temp\\Test to the path, but that didn't help.


Ive written a C ++ test:

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

It works if the second DLL (NoSenseDll) is in the same folder as the C ++ executable. This does not work if I just add the NoSenseDll folder to the PATH.

+7
python c # dll unmanaged
source share
3 answers

Draft decision:

  • Copy NoSenseDll to the Python folder, in my case %HOMEPATH%\Anaconda .
  • Restart IPython / Spyder.

Final decision:

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

Final note:

If you cannot use IronPython due to matplotlib or pandas,
if you cannot use python.net because of IPython or spyder,
if you do not want to use COM Interop just because,
and you really want C # and Python to work together, use the above solution and C # reflection.

+4
source share

You can also check out Costura.Fody.

This is a build task that will add your dependencies as resources of your build and even connect a module initializer to load them at runtime.

+2
source share

you cannot do this directly with managed code. register a COM object from your DLL:

 %SystemRoot%\Microsoft.NET\Framework\v2.0.50727\regasm.exe my.dll /tlb:my.tlb /codebase 

and call com from python. see examples here: http://www.codeproject.com/Articles/73880/Using-COM-Objects-in-Scripting-Languages-Part-Py

+2
source share

All Articles