win32com und C++ ComObjekt

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
intruder

Hallo,

ich habe mit C++ (VS 6.0) ein ComObjekt erstellt und möchte
dieses nun aus Python (2.2.1) heraus ansprechen.

Ich habe im IDL File eine struct definiert, welches ein SAFEARRAY(double)
beinhaltet.

Code: Alles auswählen

typedef
[
	uuid(19115fab-7e40-4505-9cc2-1a072fd4b033),
	version(1.0),
	helpstring("Vola Parameters for FITLib")
]	
struct VolaParams {
	[helpstring("Distribution")] long lDistribution;
	[helpstring("Type")] long lType;
	[helpstring("a CalFlag")] long  lACalFlag;
	[helpstring("b CalFlag")] long lBCalFlag;
	[helpstring("c CalFlag")] long lCCalFlag;
	[helpstring("d CalFlag")] long lDCalFlag;
	[helpstring("a")] double dA;
	[helpstring("b")] double dB;
	[helpstring("c")] double dC;
	[helpstring("d")] double dD;
	[helpstring("q")] double dQ;
	[helpstring("ks")] SAFEARRAY(double)	dKs;
} VolaParams;
im Pythoncode kann ich alle normalen Werte ganz einfach zuweisen, aber
dem Safearray kann ich leider nichts zuweisen, da gibt es immer einen Fehler

Code: Alles auswählen

import win32com.client

myCom = win32com.client.Dispatch("ComLib.FinLib")
myStruct = myCom.VolaPar
myStruct.dKs = (1,2,3,4,5)
Fehlermeldung:
Traceback (most recent call last):
File "C:\Visual Studio 6.0\com.py", line 6, in ?
myStruct.dKs = (1,2,3,4)
pywintypes.com_error: (-2147024809, 'Falscher Parameter.', None, None)

Weiß jemand wie ich dieses SafeArray in Python füllen kann?

Vielen Dank im Voraus

Christian
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Vielleicht muss du eine List ( [] ) und keine Tupel ( () ) nutzen.

Wieso lässt du Dateien für static Dispatch nicht von makepy machen?
Zuletzt geändert von Leonidas am Mittwoch 9. Februar 2005, 12:48, insgesamt 1-mal geändert.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
intruder

Danke Leonidas,

aber leider hat mir auch makepy.py nicht weiter geholfen.
Ich benutze das gleiche ComInterface auch in VBA und dort kann
ich das SafeArray so füllen:

Code: Alles auswählen

Dim vp As Lib.Params
ReDim vp.dKs(UBound(params, 1))
Call Range2DblArray(params, vp.dKs)

# my vba fill function
Sub Range2DblArray(range As Variant, arr As Variant)
    'ReDim myArray(UBound(range, 1))
    Dim i As Integer
    '..
    For i = 1 To UBound(range, 1)
        arr(i) = CDbl(range(i, 1))
    Next i
    'Range2Array = myArray
End Sub
Ich habe auch schon versucht ein array zu erzeugen und dieses
dem tuple in der com_struct zu zuweisen, aber leider auch ohne erfolg.

Code: Alles auswählen

import array
a = array.array('d', [1.4, 3.4])
b = buffer(a)
rec.dKs = b
Ich beführchte fast, dass ich in meinem ComObjekt eine Zusatzfunktion einbauen muss, die mir das SafeArray füllt.

Vielen Dank
Christian
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

List != Array!

Probiers mal so:

Code: Alles auswählen

import win32com.client

myCom = win32com.client.Dispatch("ComLib.FinLib")
myStruct = myCom.VolaPar
myStruct.dKs = [1,2,3,4,5]
Oder du schickst es mir und ich guck mir das mal an..
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
intruder

So habe eine Lösung gefunden und zwar muss man ein VARIANT übergeben:

IDL Datei
-----------------------------------------------------------------------------------

Code: Alles auswählen

struct Param {
      [helpstring("q")] double dTest;
      [helpstring("ks")] VARIANT dArray;
} Param;
Dummy Method (C++)
----------------------------------------------------------------------------------

Code: Alles auswählen

STDMETHODIMP CTest::Dummy(Param *para, double *result)
{

      VARIANT variantArray = para->dArray;

      std::vector<double> localArray;

      double dItem = 0.0;
      long lVal[1];
      long i;

      VARIANT varItem;

      long lBound = 0;
      long uBound = 0;

      SafeArrayGetLBound(variantArray.parray,1,&lBound);
      SafeArrayGetUBound(variantArray.parray,1,&uBound);

      for (i=lBound;i <= uBound; i++)
      {
            lVal[0] = i;
            SafeArrayGetElement(variantArray.parray, lVal, &varItem);

            if (varItem.vt == VT_R8)
                  localArray.push_back(varItem.dblVal);
      }

      *result = localArray[0];

      return S_OK;
}
PyCrust / Python Call
-----------------------------------------------------------------------------------

Code: Alles auswählen

import win32com.client
myCom = win32com.client.Dispatch("Com.Test")
myRec = win32com.client.Record('Param', myCom)
myRec.dArray = (1.0, 2.0, 3.0)
result = myCom.Dummy(myRec)
result
1.0
myRec.dArray = (4.5670, 2.0, 3.0)
result = myCom.Dummy(myRec)
result
4.5670000000000002
Gruß
Christian
Antworten