Array in VARIANT verpacken....



  • In Anlehnung an diesen Thread den eh keiner mehr liest...
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-114094-and-start-is-10.html

    hat sich mehr oder weniger alles geklärt ausser folgender nicht OPC-Client spezifischer frage...

    Wie zur Hölle bekomm ich mein Array in einen VARIANT typen...

    Wäre tolle wenn mir dazu jemand ein bisschen quellcode geben könnte...

    Also angenommen

    VARIANT var;
    std::vector<double> myvec;
    myvec.push_back(4711.0815);
    myvec.push_back(1234.5678);
    
    // und wie pack ich den vector jetzt in den VARIANT...
    


  • Einen STL-Container kriegst du da nicht rein. Das Zauberwort heisst SAFEARRAY.



  • Einen STL-Container kriegst du da nicht rein. Das Zauberwort heisst SAFEARRAY

    Na der da direkt nicht reinpasst war mir schon klar 😃

    Die Frage ist viel mehr das SAFEARRAY teil ist ja nur nen pointerchen... muss also für speicher allokieren (womit vermute mal stark nicht mit new...) und wenn doch allokier ich da einfach sizeof(datentyp)* grösse speicher?
    wie läuft das mit der freigabe des speichers danach...

    hast du da nicht ein codesnippet für mich?



  • Die SAFEARRAY Funktionen sind in der MSDN dokumentiert:
    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/automat/htm/chap7_5dyr.asp

    In ein SAFEARRAY kann man nicht irgendeinen Datentyp ablegen. Man muß sich auf die bei der Automatisierung üblichen Typen beschränken, da es ja sprachunabhängig funktionieren soll ( z.B. mit VB ).
    Beispiele hierfür findest du in der Dokumentation des Typ VARIANT.

    Um ein SAFEARRAY anzulegen und Speicher zu allozieren musst du die SafeArray* - Funktionen aufrufen. Bei den Funktionen sind einige Beispiele dabei.



  • @tvdog

    Ja damit spiel ich ja auch die ganze Zeit rum... Allerdings mag der den Variant der dann rauskommt irgendwie nicht und ich hab noch nicht herausgefunden warum...

    dann frag ich mal sorum... was mach ich denn falsch?

    VARIANT var;
    SAFEARRAYBOUND rgsabound[]  = {10, 0};
    VariantInit (&var);
    var.parray = SafeArrayCreate(VT_R8, 1, rgsabound);
    
    double x=4711.0815;
    for(long i=0; i<var.parray->rgsabound->cElements; i++)
    	SafeArrayPutElement(var.parray, &i, &x);
    


  • argh........ ich könnte mich schlagen..

    ich hatte die ganze Zeit

    var.vt= VT_ARRAY | VT_R8;
    

    vergessen... so ne scheisse stunden irgendwo anders den Fehler gesucht für nichts 😡

    trotzdem danke...

    aber bevor ichs vergesse noch ne frage... was muss ich mit dem var noch machen? killt der den speicher von alleine wenn der aus dem scope kommt weil er festellt sein pointer ist valid oder was muss ich alles aufrufen?



  • Für das Initialisieren und Aufrufen gibts die Funktionen

    VariantInit( &variant );

    und

    VariantClear( &variant );

    VARIANT var;
    
    // Variant auf VT_EMPTY initialisieren
    VariantInit( &var );
    
    // mal einen String reinsetzen
    V_VT(&var) = VT_BSTR;
    V_BSTR(&var) = SysAllocString( L"Hello World" );
    
    // Hier wird der Speicher, der durch den Variant belegt wird
    // freigegeben ( auch SAFEARRAYs, wenn V_VT stimmt )
    VariantClear( &var );
    


  • @tvdog
    ist denn der VariantClear mehr oder weniger zwingend wenn man kein memoryleak haben will oder wird im fall des falles wenn die variable ihren scope verliert eh abgeräumt?



  • ist denn der VariantClear mehr oder weniger zwingend wenn man kein memoryleak haben will oder wird im fall des falles wenn die variable ihren scope verliert eh abgeräumt?

    Ein Speicherbereich den du mit new oder malloc angelegt hast, wird auch nicht freigegeben wenn der Pointer aus dem scope geht. Da mußt du ja auch delete / free aufrufen sonst gibts MemoryLeaks.

    Schau dir mal die struct tagVARIANT aus oaidl.h an. Da es unter C++ einfach eine union ist musst du natürlich Speicher für einen VT_I4 oder VT_R8 nicht freigeben. Speicher für Strings oder Schnittstellen ala IDispatch / IUnknown müssen sehr wohl freigegeben werden, da sonst Memoryleaks entstehen ( ähnlich wie bei char* p = new ... ).

    Grob gesagt ist es immer vernünftig VariantClear aufzurufen (und auch guter Programmierstil). Wenn du das nicht willst, kannst du ja eine der vielen Wrapperklassen von C++ / ATL / MFC verwenden. Die machen das dann im Destruktor. Beispiele für solche Klassen sind:

    _variant_t (comdef.h)
    COleVariant (MFC)
    CComVariant (ATL)



  • @tvdog
    Ok danke...

    ach so noch ein kleine Frage...

    VARIANT var,var2
    .
    .
    .
    
    var2=var1;
    

    was passiert hier genau im falle eines safearrays? noch deinen ausführungen wird doch der speicher nicht kopiert sondern nur die pointer zeigen auf den gleichen bereich.... das heisst ich darf dann auch var auf keinen Fall VariantClear auf var aufrufen, so lange ich noch mit var2 arbeiten will. richtig?



  • Mit deiner Annahme liegst du völlig richtig, da hier nur die C union memberweise durch den Kompiler kopiert wird, nicht aber die Speicherbereiche auf die Pointer zeigen.

    Für deine benötigte Funktion gibts VariantCopy(Ind). Oder verwende doch die entsprechenden Klassen, dann brauchst du dich um diese Details nicht zu kümmern.



  • besten Dank...


Anmelden zum Antworten