Bearbeiten eines Arrays durch eine C++ DLL
-
Hallo,
ich habe folgendes Problem:
Ich möchte eine DLL schreiben (mit MS VC++6), die von VB6 einige Arrays übergeben bekommt und dann damit rechnet.
Im Moment verwende ich ein Beispiel-Projekt von http://www.vbpc.de UseDLL.
Wenn ich nun die DLL in VB aufrufe mitdim Array(1000) as single dim ZweitesArray(1000) as single dim Zahl1 as byte dim Zahl2 as byte dim Ergebnis as integer Ergebnis = USEDLL_test("test", Array(0), ZweitesArray(0), Zahl1, Zahl2)So funktioniert der Aufruf und die DLL tut etwas, z.B. Ergebnis = Zahl1 + Zahl2
Möchte ich mit folgendem Code ein Array lesen oder verändern, so kommt es zu einem Fehler
int USEDLL_test (char *t, float *p_F, int *p_A, unsigned char loops, unsigned char Verst) { int Element = 0; cout<<p_F[0]<<endl; cout<<p_F[1]<<endl; cout<<p_F[2]<<endl; int Element = 3; p_F[Element] = 13; Element++; p_F[Element] = 27; cout<<p_F[3]<<endl; cout<<p_F[4]<<endl; return(loops+Verst); }Es gibt folgende Fehlermeldung:
vb6.exe - Fehler in Anwendung
(Roter Kreis mit Kreuz, also Error) Die Anwendung in "000172100e" verweist auf Speicher in "0x042480000". Der Vorgang "read" konnte nicht auf dem Speicher durchgeführt werden.Klicken Sie ok zum beenden (vb6 ist dann weg)
Abbrechen zum debuggen (Möglichkeit mit Just In Time Debuggen vb6.exe zu untersuchen)Entfernt man alle Zeilen die p_F lesen oder schreiben, so funktioniert der Code. Evtl. machen die Cout alleine schon einen Fehler in einer DLL, jedoch auch wenn das Cout Zeug deaktiviert ist, macht der p_F[Element] = 13 Teil die Fehlermeldung.
Zum Testen habe ich den Code auch in ein C++ Projekt eingebaut. Die MainFunctionErgebnis = USEDLL_test ("test", Array, ArrayZwei,Zahl1,Zahl2);ruft die Funktion in dem Projekt auf. Bei gleichem Code funktioniert der Schnipsel oben.
Simon
-
Bist du den sicher ob ein "dim Array(1000) as single" in seinem aufbau identisch mit einem float *p_F?
Weist du ob das BasicKonstrukt Array(0) identisch ist mir einem C-Pointer auf ein Array?Wir haben vor zwei Jahren auch Versuche gemacht, mit VC 6 und VB, allerdigns mit der Übergabe von strings und sind gescheitert.
Soloange du bei fundamentalen Typen scheint es zu funktionieren, sobald amn auf Ziegertypen, Feldtypen und Strukturen
übergeht scheint es Unterschiede in der internen Darstellung der Daten zu geben, die es zumindes schwierig machen.Laäßt sich deine Fundstelle zu solchen Fragen irgendwie aus.
Mixed Language Programming ist ein sehr interessantes Thema, das wir hier ruhig diskutieren sollten.
Auch ich hätte da noch einen Informationsbedarf.
-
Tja also mit einem String hab ich keine Probleme.
Mit Ergebnis = USEDLL_test("test",...)
übergebe ich einen String an meine DLL, der dann durch
UseDLL(char *t, ... mit einem Pointer aufgenommen wird und dann durch Cout<<t<<endl; verarbeitet wird.
Auch die Übergabe einer einzelnen Single/Float Zahl funktioniert:
Bsp:
dim Array(1000) as single
Ergebnis = USEDLL_test("test",Array(0),...)und
UseDLL(char *t, float F,...)funktioniert, jedoch habe ich dann nur eine Zahl und kein Array.
Die MitDemMesserDurchDenRücken-Methode währe nun ein float *p_F = &F und dann
p_F[Element] = WertJedoch muss das doch auch besser gehen.
Ich vermute, dass das Problem folgendes ist: VB übergibt einen den Wert an der pos = Array(Element) und nur diesen, C++ erwartet jedoch einen Pointer auf den ersten Wert von dem übergebenen Array. Bei String wird StringNULL von VB übergeben. Jetzt müsste man erfahren wie man VB zur Übergebe eines ganzen Arrays bringt. (off-topic?)
Hat das schon mal wer gemacht?
Ich habe für USB eine fertige DLL der man mit USB(Array(0),4) einen Wert, bzw. einen Index auf das erste Element übergibt. Diese liest dann auch die nächsten (4) Elemente.
Simon
-
Ähm, zu der Frage...
Also meine Funstelle lässt sich über Pointer und Arrays nicht aus. Nur eben ein String und Zahlen vom Typ double werden als Beispiel übergeben.
Simon
-
Strings der kam zwar im C an und konnte dort ausgegeben werden, wurde der String allerdings in
C- bearbeitet und zurückgeliefert, so kam es ab und zu (allerdings nicht nachvollziehbar) Fehlern
in den letzten Zeichen, sah fast wie eine Alignment Problem aus konnte aber durch geändertes
Alignment nicht korrigiert werden.
-
Dein Ansatz mit der DLL ist ungeschickt, weil Du im Aufbau der DLL sehr viele interne Details aus C++ einbaust, die Du dann beim Aufruf von VB beachten mußt. Z.B. kannst Du die Typen völlig frei wählen, das macht es natürlich fehleranfällig.
Die richtige Lösung wäre in C++ ein COM-Objekt zu schreiben - durch die Interface-Definition-Language (IDL) sind nämlich dann alle Typen definiert und austauschbar. In VB ziehst Du das Objekt dann einfach in Dein Projekt rein und die Übergabe aller Werte klappt sofort. Du kannst das mal mit den Assistenten vom VStudio testen, einfache COM-Server lassen sich dort via Assistent fast automatisch generieren. Das Ergebnis bindest Du in einem VB-Projekt ein.
Ach ja, lass Dich nicht täuschen daß dieses Ergebnis auch in einer DLL erzeugt wird... es ist trotzdem etwas anders als die bisher von Dir verwendete DLL.
Ich denke mal, in der Rubrik MFC sitzen die geeigneten Fachleute für diese Herangehensweise... ich schiebe das dorthin.
-
Es gibt eine Datei "Vb5dll.doc" (mal googlen) in der ist beschrieben wie Daten von VB -> C/C++ übergeben werden können. Auch Strukuren (keine Klassen). Die o.g. Datei ist auch auf irgendeiner VB-CD mit drauf, weiß aber grad nicht welche.