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 hierdouble *
). 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: 1Die 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 überarbeitetEDIT:
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]; }