call c# dll functions from python 2.5

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Theo
User
Beiträge: 17
Registriert: Montag 24. August 2009, 16:11
Kontaktdaten:

Hi,

der Simulator den ich nutze hat ein Python upgrade erfahren, von Version 2.2 auf 2.5 ( ja ich weiss total aktuell ... )

Nun gibt es folgendes Problem.

Ich habe bestimmte Komponenten, die auf Funktionen einer C# dll zugreifen. Das hab ich damals mit calldll gemacht, war alles bissl umstaendlich, aber es ging am Ende.

Nun mit der Version 2.5 gibt es das calldll modul leider nicht mehr. Ich hab gestern ewig im Netz gesucht, ob es etwas equivalentes mit 2.5 gibt. Ich bin immer nur auf ctypes gestossen, aber soweit ich weiss funktioniert das nur mit c/c++ - Dlls

Ok nun die Frage an euch, gibt es mit Version 2.5 irgendwie die Möglichkeit Funktionen einer C# Dll von Python aus aufzurufen?!

Vielen Dank schonmal,
Theo
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ist IronPython denn eine Option? Da Python dann direkt auch der CLR laeuft sollte das kein Problem sein.
Zu ctypes kann ich da leider nichts sagen.
Theo
User
Beiträge: 17
Registriert: Montag 24. August 2009, 16:11
Kontaktdaten:

cofi hat geschrieben:Ist IronPython denn eine Option? Da Python dann direkt auch der CLR laeuft sollte das kein Problem sein.
Nope ist leider keine Option, da die Skriptsprache fest im Simulator enthalten ist, also am klassichen Python komm ich leider nicht drumherrum
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Was denn für ein ``calldll``-Modul? Ich denke nicht dass so ein Modul Teil von Python 2.2 war und inzwischen entfernt wurde.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Theo
User
Beiträge: 17
Registriert: Montag 24. August 2009, 16:11
Kontaktdaten:

Leonidas hat geschrieben:Was denn für ein ``calldll``-Modul? Ich denke nicht dass so ein Modul Teil von Python 2.2 war und inzwischen entfernt wurde.
Ui ka, von welcher Version das war. Wo ich damals wegen dem gleichen Problem gesucht habe, bin ich auf eine Seite gestossen wo das beschrieben war und da gabs die 'calldll.pyd' zum herunterladen
BlackJack

@Theo: Das klingt eigentlich nach Sam Rushings `calldll`; Teil von DynWin: http://www.nightmare.com/~rushing/dynwin/

Allerdings sieht das nach einem Modul aus, mit dem man "native" DLLs ansprechen kann. .NET-DLLs enthalten ja AFAIK keinen Maschinencode den man "normal" aufrufen kann. Da Rushing als Ersatz `ctypes` aus der Standardbibliothek empfiehlt, kann es ja irgendwie nicht das gewesen sein, was Du verwendet hast!?
Theo
User
Beiträge: 17
Registriert: Montag 24. August 2009, 16:11
Kontaktdaten:

Ok hier mal ein kleiner Auszug aus dem Script

Code: Alles auswählen

from vcScript import *
import calldll
import struct

def GetMemAlloc( size, format, value ):
  refMem = calldll.membuf( size )
  string_packed = struct.pack( format, value )
  refMem.write( string_packed )
  return refMem
  
  
def CreateMemInt( value ):
  return GetMemAlloc( 4, "i", value )
  
def CreateMemDouble( value ):
  return GetMemAlloc( 8, "d", value )
  
def CreateMemString( value ):
  length = len( value ) + 1
  return GetMemAlloc( length, str(length) + "c", value )
  
  
def ReadMemInt( refValue ):
  return struct.unpack("i", refValue.read())[0]
  
def ReadMemDouble( refValue ):
  return struct.unpack("d", refValue.read())[0]
  
def ReadMemString( refValue ):
  return calldll.read_string( refValue.address() )


def LoadDLL( dll_name ):
  global dll_handle
  dll_handle = calldll.load_library( dll_name )
  
def LoadMethod( method_name ):
  global dll_handle
  if dll_handle != 0:
    return calldll.get_proc_address(dll_handle, method_name )
  else:
    return 0;



def AddExternal( A, B ):
  handle_method = LoadMethod( "Add" )
  refA = CreateMemInt( A )
  refB = CreateMemInt( B )
  refResult = CreateMemInt( -1 )
  calldll.call_foreign_function( handle_method, 'lll', '', (refA.address(), refB.address(), refResult.address()) )
  Result = ReadMemInt( refResult )
  return Result
  
  ...
  ...

def StartSpeedSimulation():
  handle_method = LoadMethod( "StartSimulationAtFullSpeed" )
  refErrorCode = CreateMemInt( -1 )
  calldll.call_foreign_function( handle_method, 'l', '', (refErrorCode.address(),) )
  print "error code : " + str( ReadMemInt(refErrorCode) )
  
def StopSpeedSimulation():
  handle_method = LoadMethod( "StopSimulation" )
  refErrorCode = CreateMemInt( -1 )
  calldll.call_foreign_function( handle_method, 'l', '', (refErrorCode.address(),) )
  print "error code : " + str( ReadMemInt(refErrorCode) )
  
  ...
  ...
  
def OnRun():
  global dll_handle
  print "enter onrun"
  
  
  # get access
  LoadDLL( 'SpeedSimulatorWrapper.dll' )
  
  # trivial tests
  print "trival interface tests:"
  print AddExternal( 5, 6 )
  
  ...
  ...
  
  calldll.free_library(dll_handle)
  print "exit onrun"
Also fuer mich war das damals ein enormes gebastle. Leider funktioniert diese 'calldll.pyd' mit der Python-Version 2.5 des Simulators nicht mehr.

Ich hab jetzt schon probiert den Umweg mittels ctypes zu gehen: Python <-> C++/CLI-DLL <-> C#-DLL
Funktioniert leider nicht, da bekomm ich den Fehler: ' WindowsError: exception code 0xe0434f4d'


Das 'C++/CLI-DLL <-> C#-DLL' funktioniert auch problem los, hab dies getestet in dem ich den Python-Teil durch eine C++ (Konsolenanwendung) <-> C++/CLI-DLL <-> C#-DLL ersetzt habe

Irgendwie ist da der Wurm drin :'(
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Naja, du müsstest schon den ``ctypes``-Code zeigen, damit man da irgendwas dazu sagen kann…
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Theo
User
Beiträge: 17
Registriert: Montag 24. August 2009, 16:11
Kontaktdaten:

Code: Alles auswählen

from vcScript import *
from ctypes import *

def ButtonTestDll_click( prop ):
  
  x = CDLL( _sPathToDll.Value.split( "file:///" )[1] ) #path to 'PythonAndCPlusPlus.dll'
  print x

  f = c_int(5)
  print f
  
  print str( x.fakultaet( f ) )
  
_comp = getComponent()

_sPathToDll = _comp.getProperty( "PathToDll" )
_buttonTestDll = _comp.getProperty( "TestDll" )
_buttonTestDll.OnChanged = ButtonTestDll_click
Und das kommt dann als Fehlermeldung am Ende raus

<CDLL 'D:\SVN_VC\projects\_Dualis\C_Sharp_Projects\PythonAndCPlusPlus\Debug\PythonAndCPlusPlus.dll', handle 650a0000 at 17102ff0>
c_long(5)
Error at "Name::PythonSkript":
Traceback (most recent call last):
File "Name::PythonSkript", line 12, in ButtonTestDll_click
WindowsError: exception code 0xe0434f4d

PythonAndCPlusPlus.cpp

Code: Alles auswählen

#include "stdafx.h"
#include "PythonAndCPlusPlus.h"

using namespace PythonAndCSharp;
#using <D:\SVN_VC\projects\_XXX\C_Sharp_Projects\PythonAndCSharp\PythonAndCSharp\bin\Debug\PythonAndCSharp.dll>


// Berechnet die Fakultaet einer ganzen Zahl
int fakultaet(int n)
{
	
	return PythonAndCSharp::Class1::fakultaet(n);
}
PythonAndCPlusPlus.h

Code: Alles auswählen

#pragma once

using namespace System;

// Berechnet die Fakultaet einer ganzen Zahl 
extern "C" __declspec(dllexport) int __cdecl fakultaet(int n);
PythonAndCSharp.cs

Code: Alles auswählen

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Reflection;


namespace PythonAndCSharp
{
    public class Class1
    {
        public static int fakultaet(int n)
        {
            int i;
            int ret = 1;
            for (i = 1; i <= n; i++)
            {
                ret *= i;
            }
            return ret;
        }
    }
}
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

C++ funktioniert hier, da es sowohl im managed als auch unmanaged Modus laufen kann. Probier mal, den C++-Teil mit einem #pragma unmanaged bei gesetztem /clr Flags zu versehen.

Weitere Infos hierzu:
- http://msdn.microsoft.com/en-us/library/ms973872.aspx
- http://msdn.microsoft.com/en-us/library/ms173266.aspx

Alternativ kannst Du den C#-Code auch als COM-Objekt anlegen und darüber zugreifen. Das zumindest ist der von MS empfohlene Weg. Die native Anbindung über eine Flat-API mit C++-Wrapper ist für komplexere Parameterübergabe oder Rückgabe fehlerträchtig.
Antworten