Parameterübergabe: Übersetzung von "REF" aus C# nach C++



  • Hallo,

    wie ich schon in meinem vorherigen Beitrag schrieb, versuche ich den C#-Quelltext von http://www.codeproject.com/cs/miscctrl/loadandsave.asp in C++ zu übersetzen.
    Das wesentliche habe ich bereits fertig, aber ein weiteres Problem (bei der Parameterübergabe), bekomme ich selbst einfach nicht gelößt:

    public static int loadTree(TreeView tree, string filename)
    		{
    			if (File.Exists(filename))
    			{
    				// Datei öffnen
    				Stream file = File.Open(filename, FileMode.Open);
    				// Binär-Formatierer init.
    				BinaryFormatter bf = new BinaryFormatter();
    				// Object var. init.
    				object obj = null;
    				try
    				{
    					// Daten aus der Datei deserialisieren
    					obj = bf.Deserialize(file);
    				}
    				catch (System.Runtime.Serialization.SerializationException e)
    				{
    					MessageBox.Show("De-Serialization failed : {0}", e.Message);
    					return -1;
    				}
    				// Datei schliessen
    				file.Close();
    
    				// Neues Array erstellen
    				ArrayList alist = obj as ArrayList;
    
    				// Für jedes Objekt in der ArrayList
    				foreach (object item in alist)
    				{
    					// Objekt in Hashtable konvertieren
    					Hashtable ht = item as Hashtable;
    					// Neue TreeNode erstellen
    					TreeNode tn = new TreeNode(ht["Text"].ToString());
    					// Daten aus dem Hash laden
    					tn.Tag = ht["Tag"];
    					tn.ImageIndex = Convert.ToInt32(ht["SelectedImageIndex"].ToString());
    					tn.SelectedImageIndex = Convert.ToInt32(ht["SelectedImageIndex"].ToString());
    
    					// die Parent-Child-Zuordnung 
    					string fPath = ht["FullPath"].ToString();
    					// FullPath teile in ein string-Array
    					string[] parts = fPath.Split(tree.PathSeparator.ToCharArray());
    					// Wenn das Array mind. 2 Teile hat 
    					if (parts.Length > 1)
    					{
    						// ParentNode variable init.
    						TreeNode parentNode = null;
    						TreeNodeCollection nodes = tree.Nodes;
    						// rekursives durchsuchen der Nodes
    						searchNode(parts, ref parentNode, nodes);
    
    						if (parentNode != null)
    						{
    							// Eine ParentNode wurde gefunden, also aktuelle Node unter dieser hinzuf.
    							parentNode.Nodes.Add(tn);
    						}
    					}
    						// Ansonsten Node nur zum Tree hinzuf.
    					else tree.Nodes.Add(tn);
    				}
    				return 0;
    			}
    			else return -2; // File existiert nicht
    		}
    
    		private static void searchNode(string[] parts, ref TreeNode parentNode, TreeNodeCollection nodes)
    		{
    			foreach (TreeNode n in nodes)
    			{
    				// Wenn der Text der TreeNode (n) dem der ParentNode (laut FullPath) entspricht
    				if (n.Text.Equals(parts[parts.Length - 2].ToString()))
    				{
    					// ParentNode setzen
    					parentNode = n;
    					// ende
    					return;
    				}
                    // ansonsten -> rekursiver Aufruf dieser Funktion
    				else searchNode(parts, ref parentNode, n.Nodes);
    			}
    		}
    		#endregion
    	}
    

    Meine Übersetzung: 🙄

    static int loadTree(TreeView * tree, String * filename)
    	{
    		if (System::IO::File::Exists(filename))
    		{
    
    			// Datei öffnen
    			System::IO::Stream * file = System::IO::File::Open(filename, System::IO::FileMode::Open);
    
    			// Binär-Formatierer init.
    			System::Runtime::Serialization::Formatters::Binary::BinaryFormatter * bf = new System::Runtime::Serialization::Formatters::Binary::BinaryFormatter();
    
    			// Object var. init.
    			Object * obj = 0;
    
    			try
    			{
    				// Daten aus der Datei deserialisieren
    				obj = bf->Deserialize(file);
    			}
    			catch (System::Runtime::Serialization::SerializationException * e)
    			{
    				MessageBox::Show("Ent-Serialisation gescheitert : {0}", e->Message);
    			}
    
    			file->Close();
    
    			tree->Nodes->Clear();
    
    			// Neues Array erstellen
    			ArrayList * alist = new ArrayList();
    			alist = static_cast<ArrayList *>(obj);
    
    			for (int i = 0; i < alist->get_Count(); i++)
    			{
    				Object * item = alist->Item[i];
    
    				// Objekt in Hashtabelle konvertieren
    				Hashtable * ht = new Hashtable();
    				ht = static_cast<Hashtable *>(item);
    
    				TreeNode * tn = new TreeNode(ht->get_Item(S"Text")->ToString());
    
    				// Daten aus dem Hash laden
    				tn->Tag = ht->get_Item(S"Tag");
    
    				// die Parent-Child-Zuordnung
    				String * fPath = ht->get_Item(S"FullPath")->ToString();
    
    				//MessageBox::Show(fPath);
    
    				// FullPaht-Teile in ein string-Array
    				String * parts[] = fPath->Split(tree->PathSeparator->ToCharArray());
    
    			//	MessageBox::Show(parts->Item->);
    
    				// Wenn das Array mind. 2 Teile hat
    				if (parts->Length > 1)
    				{
    					// ParentNode variable init.
    					TreeNode * parentNode = new TreeNode();
    					parentNode = 0;
    
    					TreeNodeCollection * nodes = tree->Nodes;
    					searchNode(parts, *parentNode, nodes);
    
    					if (parentNode != 0)
    					{
    						// Eine ParentNode wurde gefunden, also akutelle Node unter dieser hinzuf.
    						parentNode->Nodes->Add(tn);
    					}
    				}
    				else
    					tree->Nodes->Add(tn);
    
    			}
    			return 0;
    		}
    		else
    			return -2;		
    	}
    

    Das Problem liegt, glaube ich zumindest, bei der Übergabe des Parameters parentNode an die Funktion searchNode.

    static void searchNode(String * parts[], TreeNode &parentNode /* !!!! DIESER PARAMETER !!!! */, TreeNodeCollection * nodes)
    	{
    		//MessageBox::Show("searchNode");
    
    		for (int i = 0; i < nodes->get_Count(); i++)
    		{
    			MessageBox::Show("Schleife");
    			TreeNode * n = new TreeNode;
    			n = nodes->Item[i];
    
    			// Wenn der Text der TreeNode (n) dem der ParentNode (laut FullPath) entspricht
    			if (n->Text->Equals(parts[parts->Length - 2]->ToString()))
    			{
    				// ParentNode setzen
    
    				parentNode.Nodes->Clear();
    				parentNode->Nodes.Add(nodes->Item[i]);
    				//ende
    				return;
    			}
    			else
    			{
    				searchNode(parts, parentNode, n->Nodes);
    			}
    		}
    	}
    


  • Ich habe das jetzt nicht alles durchgelesen, aber so sollte es gehen

    void searchNode(String * parts[], TreeNode ** parentNode /* !!!! DIESER PARAMETER !!!! */, TreeNodeCollection * nodes)
    


  • Alzo das ist schon ein heikles Thema. Ausserdem solltest du diese Techniken nicht zu häufig verwenden, da sonst dein Quelltext unlesbar wird.

    #pragma managed
    
    System::Void refptr(System::String __gc *__gc *Ref)
    {
    	(*Ref) = S"Hallo Welt\n";
    }
    
    System::Int32 main()
    {
    	System::String __gc *Str;
    	refptr(&Str);
    	System::Console::Out->Write(Str);
    	return 0;
    }
    

    Das ist vielleicht nicht ganz das gleiche, aber es könnte dir helfen. Du musst nur darauf achten, das du niemals die Adresse eines lokalen Objekts mit return übergibst, denn das gibt Probleme 😉 .



  • Danke für die Antworten!

    💡 Das Problem scheint nun gelößt zu sein. 🙂 🙂 🙂

    @Scania: Deinen Vorschlag habe ich sofort ausprobiert, aber der Compiler war mit dieser Lösung nicht so recht zufrieden. 🙂 😉



  • ???
    Bei mir funktioniert dies Einwandfrei, genauso wie der Compiler automatisch "" in __gc umwandelt, wandelt er auch "**" in __gc* __gc* um.


Anmelden zum Antworten