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
call c# dll functions from python 2.5
- 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.
Zu ctypes kann ich da leider nichts sagen.
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
Nope ist leider keine Option, da die Skriptsprache fest im Simulator enthalten ist, also am klassichen Python komm ich leider nicht drumherrumcofi hat geschrieben:Ist IronPython denn eine Option? Da Python dann direkt auch der CLR laeuft sollte das kein Problem sein.
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 herunterladenLeonidas 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.
@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!?
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!?
Ok hier mal ein kleiner Auszug aus dem Script
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 :'(
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"
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 :'(
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
<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);
}
Code: Alles auswählen
#pragma once
using namespace System;
// Berechnet die Fakultaet einer ganzen Zahl
extern "C" __declspec(dllexport) int __cdecl fakultaet(int n);
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;
}
}
}
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.
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.