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.htmlhat 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.aspIn 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.
-
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...