Aufruf einer C++-Funktion in Visual Basic



  • Hallo!

    Wie kann ich folgende C++-Funktion von Visual Basic aus aufrufen?

    namespace nowhere
    {
    	public ref class Class1
    	{
    		public:
    			void doSomething(double*, double *);
            };
    }
    

    VB-Aufruf:

    Dim instanceOfClass1 As Class1 = new Class1
    instanceOfClass1.doSomething( <---------------joa wie gehts weiter??
    

    Kann mir jemand weiter helfen?

    Grüße Stefan



  • Hallo,
    ich glaube, ich muss dich leider enttäuschen: Visual Basic.NET unterstützt keine native Pointer (in C++/CLI: typename * , in deinem Fall hier double * ). Damit du die Methode dennoch benutzen kannst solltest du den Ansatz mit den Pointern daher überdenken. Besteht eventuell die Möglichkeit, tracking references zu verwenden? Denn das wäre vermutlich die optimale Variante:

    namespace nowhere
    {
        public ref class Class1
        {
            public:
                void doSomething(double%, double%);
        };
    }
    

    Diese Variante entspricht in Visual Basic in etwa folgendem:

    Namespace nowhere
    
        Public Class Class1
    
            Public Sub doSomething(ByRef a As Double, ByRef b As Double)
                ' Do stuff...
            End Sub
    
        End Class
    
    End Namespace
    
    '
    ' Und der Aufruf...
    '
    Dim a, b As Double
    Dim c As New nowhere.Class1()
    c.doSomething(a, b)
    

    Hoffe, ich konnte dir helfn 😉
    MfG



  • hey! kannst du das mit "tracking reference" genauer erklären? bin neu in .NET..



  • piwi133 schrieb:

    Hallo!

    Wie kann ich folgende C++-Funktion von Visual Basic aus aufrufen?

    namespace nowhere
    {
    	public ref class Class1
    	{
    		public:
    			void doSomething(double*, double *);
            };
    }
    

    VB-Aufruf:

    Dim instanceOfClass1 As Class1 = new Class1
    instanceOfClass1.doSomething( <---------------joa wie gehts weiter??
    

    Kann mir jemand weiter helfen?

    Grüße Stefan

    Versuche doch das ganze in eine dll zu packen und dann ins net-Programm einzubinden.



  • Abent^^

    piwi133 schrieb:

    hey! kannst du das mit "tracking reference" genauer erklären? bin neu in .NET..

    Selbstverständlich! 😃
    Eine tracking reference entspricht grundsätzlich einer normalen C++ reference:

    int wat = 47;
    int &ref = wat; // reference
    int %tracking_ref = wat; // tracking reference
    

    Die Art der Verwendung ist bei beiden reference Typen dieselbe. Nun gibt es aber bedingt durch die Speicherverwaltung der CLI einige Unterschiede, welche berücksichtigt werden müssen. Stell dir folgende Situation vor:

    ref class Foo
    {
    public:
        int wat; // jetzt ist deine Variable Teil eines Objektes.
    };
    

    Jede Instanz dieser Klasse steht unter der Verwaltung der CLI; die Garbage Collection übernimmt die Speicherverwaltung. Nun ist es aber der Speicherverwaltung erlaubt, die Objekte im Speicher neu zu arrangieren, sprich die Adresse der Instanz kann sich verändern während du sie verwendest. Willst du nun deine Instanzvariable per reference ansprechen, so darfst du dies nur per tracking reference tun, weil diese ebenfalls unter der Verwaltung der CLI stehen und somit vom GC ebenfalls verändert werden können, sobald sich die Instanz bewegt. Eine normale reference würde in diesem Fall aus unersichtlichen Gründen plötzlich ungültig, weil sie immer noch auf die alte Adresse verweisen würde.

    Hoffe das ist soweit klar. Kommen wir zum nächsten Punkt: Jede reference kann als tracking reference gehandelt werden, da sich der Speicher in diesem Fall nicht bewegt. Umgekehrt geht das aber nicht, sprich für eine normale reference kannst du keine tracking reference übergeben. Das dumme ist nur, dass das Konzept von tracking reference und normalen references nur in C++/CLI (und MSIL natürlich) unterschieden wird - alle anderen Sprachen wie etwa VB.Net kennen nur tracking references.

    BTW: Es ist schon sehr lange her, seit ich mal etwas mit VB gemacht habe - und nur zum sicher sein: Wir reden hier schon über VB.Net? 😉



  • danke dir für die ausführliche Erklärung!
    aber wie kann ich mit tracking reference die Adresse von wat abfragen?

    int wat = 27;
    		int &ref = wat;
    		std::cout << "&ref: " << &ref << std::endl;
    		int %ref2 = wat;
    		std::cout << "ref2: " << ref2 << std::endl;
    		std::cout << "&ref2: " << &ref2 << std::endl;
    

    Output:
    &ref: 0377F21C
    ref2: 27
    &ref2: 1



  • piwi133 schrieb:

    aber wie kann ich mit tracking reference die Adresse von wat abfragen?

    int wat = 27;
    		int &ref = wat;
    		std::cout << "&ref: " << &ref << std::endl;
    		int %ref2 = wat;
    		std::cout << "ref2: " << ref2 << std::endl;
    		std::cout << "&ref2: " << &ref2 << std::endl;
    

    Output:
    &ref: 0377F21C
    ref2: 27
    &ref2: 1

    Die Antwort lautet: gar nicht! Die Adresse des Objektes kann ja variieren - und die Variation erfolgt nicht-deterministisch; die Verwendung einer nativen Adresse ergibt deshalb keinen Sinn. Allerdings gibt es einen Weg, die Adresse dennoch sicher zu bekommen. Du kannst sie dir holen, indem du die Adresse der tracking reference in einem so genannten pinning pointer ablegst. Damit stellst du sicher, das der Speicher, indem sich das per tracking reference angesprochene Element befindet, nicht bewegt. Sobald dies der Fall ist kann man das Objekt auch mittels einer normalen reference/pointer verwenden:

    int foo = 1000;
    
        int &ref = foo;
        int %t_ref = foo;
    
        cli::pin_ptr<int> p_ref = &t_ref; // pinning pointer
    
        wcout << L"t_ref: " << (int *)p_ref << endl;
    


  • ah wunderbar! danke nochmal!!
    jetzt habe ich aber noch eine Frage 😃 :

    Wie muss ich konvertieren, dass

    xValues = xVals;
    

    passt?

    xVals und xValues sind wie folgt erfolgreich angelegt:

    xVals = new double[nnodes];
    array<double>^ xValues = gcnew array<double> (nnodes);
    


  • piwi133 schrieb:

    ah wunderbar! danke nochmal!!
    jetzt habe ich aber noch eine Frage 😃 :

    Wie muss ich konvertieren, dass

    xValues = xVals;
    

    passt?

    xVals und xValues sind wie folgt erfolgreich angelegt:

    xVals = new double[nnodes];
    array<double>^ xValues = gcnew array<double> (nnodes);
    

    Grundsätzlich sind die beiden Arrays nicht miteinander kompatibel; es existiert keine allgemeine Zuweisungsoperation. Du kannst natürlich von Hand alle Elemente von einem unmanaged Array in ein managed Array kopieren, oder eine Funktion aus dem Header <algorithm> benutzen^^



  • lol da hätte ich auch selber drauf kommen können^^
    ich bin überarbeitet 😃

    EDIT:
    komm einfach nicht drauf wie es bei einem 2dimensionalen Feld geht!

    listVals = new int*[nelements];
    		for(int i=0; i<nelements; i++)
    			listVals[i] = new int[numberOfCol];
    
    		array<int, 2>^ listValues = gcnew array<int, 2> (nelements,
                                    numberOfCol);
    
    //Hier Fkt. um Werte für listVals einzulesen
    
    		for(int i=0; i<nelements; i++)
    		{
    			for(int j=0; j<numberOfCol; j++)
    				listValues[i][j] = listVals[i][j];
    		}
    

    Bekomme immer die Fehlermeldung: error C3262: Ungültige Array-Indizierung: 1 Dimension(en) wurden für 2-dimensionales 'cli::array<Type,dimension> ^' angegeben

    EDIT #2:
    ich habs:

    listVals = new int*[nelements];
    		for(int i=0; i<nelements; i++)
    			listVals[i] = new int[numberOfCol];
    
    		array<Int32, 2>^ listValues = gcnew array<Int32, 2> (nelements,
                         numberOfCol);
    
    //Hier Fkt. um Werte für listVals einzulesen
    
    		int i, j;
    		for(i=0; i<nelements; i++)
    		{
    			for(j=0; j<numberOfCol; j++)
    				listValues[i,j] = listVals[i][j];
    		}
    

Log in to reply