Seite 1 von 1

win32com 'pass by reference' problem

Verfasst: Samstag 16. Februar 2008, 22:58
von irimi
Hallo,

nachdem ich nach diversen Recherchen per Suchmaschine nicht weiterkomme, will ich es mal hier versuchen :D

Wie ich verstanden habe: wenn ich nun eine Funktion meines COM Servers aufrufen will, die eine "pass by reference" value hat, gibt die win32com Implementierung von Python ein Tupel zurück:

Code: Alles auswählen

long GeValue(LPCTSTR device, short Value)
wird

Code: Alles auswählen

ret, value = GetValue("mein device") 
o.ä. !?

Nun bekomme ich aber bei der Funktion, die ich bei "meinem" COM Server absprechen will, aber immer folgende Fehlermeldung

Code: Alles auswählen

self.__server = win32com.client.Dispatch(self.__AUTO_APPL)

def getValue(self,identifier,offset,size):
      retVal=None
      if self.__server:
          result, answer=self.__server.GetValueBySymbol(identifier,offset,size)
            retValue=answer
      return retVal

  result, answer=self.__server.GetValueBySymbol(symbol,offset,size)
  File "<COMObject Auto.Application>", line 2, in GetValueBySymbol
pywintypes.com_error: (-2147352561, 'Parameter nicht optional.', None,
None)

Bediene ich diesen Parameter, gibt es eine andere Fehlermeldung

Code: Alles auswählen

   def getValue(self,identifier,offset,size):
        retVal=None
        answer = [] # =None als Alternative gleich
        if self.__server:
            result, answer=self
.__server.GetValueBySymbol(identifier,offset,size,answer)
            retValue=answer
        return retVal

 result, answer=self.__server.GetValueBySymbol(symbol,offset,size,answer)
  File "<COMObject Auto.Application>", line 2, in GetValueBySymbol
pywintypes.com_error: (-2147352571, 'Typkonflikt.', None, 4)
Die IDL des COM Servers, den ich ansprechen will sieht so aus:

Code: Alles auswählen

[id(2), helpstring("method GetValueBySymbol")] long GetValueBySymbol(BSTR szSymbol, short shOffset, short shLength, [out,retval] VARIANT* pValue);
makepy sagt mir folgendes:

Code: Alles auswählen

# Created by makepy.py version 0.4.95

      def GetValueBySymbol(self, szSymbol=defaultNamedNotOptArg,shOffset=defaultNamedNotOptArg, shLength=defaultNamedNotOptArg,pValue=pythoncom.Missing):
            """method GetValueBySymbol"""
            return self._ApplyTypes_(2, 1, (3, 0), ((8, 0), (2, 0), (2, 0),(16396, 10)), 'GetValueBySymbol', None,szSymbol, shOffset, shLength,pValue)
Und in Perl funktioniert es ohne Probleme mit

Code: Alles auswählen

sub AUTO_bGetValue {
      my $self     = shift;
      my $symbol   = shift;
      my $offset   = shift || 0;
      my $length   = shift || 1;
      my $dataref  = shift || undef;
      my $response = Variant(VT_BYREF|VT_VARIANT, Variant(VT_BSTR, ""));
      my $rc       = 0;

      &LIB_vLog("GetValue $symbol offset $offset length $length");
      if ($self->{objApp}->GetValueBySymbol($symbol, $offset, $length,$response) == 0) {
            $rc = 1;
            &LIB_vLog("GotValue $response");
            $$dataref = $response if (defined $dataref);
      }
      else {
            &LIB_vLog("Failed (error while getting value!)");
      }
      return $rc;
}
Muss ich einen bestimmten Win32Type benutzen oder wie ?? Den COM Server kann ich leider nicht ändern, da er nicht von mir ist.

irimi

Verfasst: Sonntag 17. Februar 2008, 00:29
von audax
Auch, wenn es Problem nicht löst:

Der Perl-Code ist hässlich!
Und der Python-Code auch...
Tu dir mal Perl Best Practices und PEP 8 an!

Und warum taucht da eine deutsche Fehlermeldung auf? Oo

Verfasst: Sonntag 17. Februar 2008, 01:43
von Leonidas
audax hat geschrieben:Und warum taucht da eine deutsche Fehlermeldung auf? Oo
Weil die COM-Fehlermeldungen in der Sprache sind, auf die die Applikation eingestellt ist. Das machen sogar Komponenten, die in Windows schon mitgeliefert sind. :evil:

Verfasst: Sonntag 17. Februar 2008, 19:07
von irimi
audax hat geschrieben: Der Perl-Code ist hässlich!
Und der Python-Code auch...
Tu dir mal Perl Best Practices an!
Sorry, da "tu" ich mir eher ein Python Buch an, da ich von Perl keine Ahnung habe und das auch so belassen will (& btw der Code auch nicht von mir stammt).

Der Python Code ist auf das eigentliche Problem reduziert und bei copy/paste hat halt die Formatierung gelitten ...
aber das ist ja wohl kein Problem oder :wink:

Aber hat denn keiner einen kleinen Tipp wie der Funktionsaufruf korrekt in Python funktioniert ?

irimi

Verfasst: Dienstag 19. Februar 2008, 13:57
von mkesper
Möglicherweise liegt die Antwort in diesem Thread versteckt? (Erster Treffer auf "google: win32com parameter not optional")

Verfasst: Mittwoch 20. Februar 2008, 11:15
von irimi
mkallas hat geschrieben:Möglicherweise liegt die Antwort in diesem Thread versteckt? (Erster Treffer auf "google: win32com parameter not optional")
Herzlichen Dank !!! Man muss also nur die richtigen Suchbbegriffe eingeben :roll:

Habe es zwar noch nicht zum Laufen gebracht, aber dieser Thread bringt mich jednfalls schon mal weiter !! :D

Gelöst

Verfasst: Mittwoch 20. Februar 2008, 12:35
von irimi
irimi hat geschrieben:
mkallas hat geschrieben:Möglicherweise liegt die Antwort in diesem Thread versteckt? (Erster Treffer auf "google: win32com parameter not optional")
Herzlichen Dank !!! Man muss also nur die richtigen Suchbbegriffe eingeben :roll:

Habe es zwar noch nicht zum Laufen gebracht, aber dieser Thread bringt mich jednfalls schon mal weiter !! :D
Bingo ! Problem mit Hilfe des o.g. Tipps gelöst, man muss win32com.client.gencache verwenden:

Code: Alles auswählen

class MyClass(object):

    CLSID = pywintypes.IID('{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}')
    MajorVersion = 1
    MinorVersion = 0
    LCID = 0x0

    APPLICATION = "MyApplication.Application"
    
    def __init__(self):
        self.__early=win32com.client.gencache.EnsureModule(self.CLSID, self.LCID, self.MajorVersion, self.MinorVersion)
        self.__appl = win32com.client.Dispatch(self.APPLICATION)
        self.__appl = self.__early.MyApplication(self.__appl)
        #print repr(self.__appl)

    def getValue(self, identifier, offset, size):
        result, answer=self.__appl.GetValueBySymbol(identifier, offset, size)
        return answer

Danke,
irimi

Verfasst: Mittwoch 20. Februar 2008, 13:35
von Leonidas
Wozu brauchst du doppelte Unterstriche? Diese markieren nichts als "privat", sie sind nur dazu da um Namenskonflikte zu verhindern.