C++ DLL - Visual Basic - übergabe der Var.



  • Hallo

    sry²

    Es ist ein Programm, welches in VB geschrieben ist - ist schon fertig!
    Ich soll nun eine C++ DLL dazuprogrammieren da die Sortierung in VB ziemlich langsam ist. Es soll eine Sort und Add Funktion in der DLL enthalten sein, welche man in VB aufrufen kann. Bei Add wird ein Wert übergeben und dieser wird in einer Liste (DVL) gespeichert (als Global). Bei Sort wird nichts übergeben - es soll einfach die Fkt in C++ aufgerufen werden und die Liste sortiert werden mittels Quicksort(wird gerade umgeschrieben). Und nun möchte ich auf die Liste von C++ (DLL) in VB zugreifen können.

    😋 Danke 😋



  • Und was sind das für Dinger, die da sortiert werden sollen? Zahlen? Strings?



  • uhi..ich "vergissmeinnciht"

    zZ sind es ganz normale Integer.
    Später dann sollen es auch noch Strings, Double und Objekte(k.A) sein.

    Also wenn ich nun die Add Fkt von VB aus aufrufe wird ein Wert übergeben und dieser in einer Liste gespeichert (ist global angelegt) - das funkt schon...



  • c147258 schrieb:

    Also wenn ich nun die Add Fkt von VB aus aufrufe wird ein Wert übergeben und dieser in einer Liste gespeichert (ist global angelegt) - das funkt schon...

    Das ist auch das kleinste Problem.

    Ich denke, es ist nicht möglich, eine verkette Liste von C++ nach VB zurückzugeben, ohne dass man Funktionsaufrufe benötigt, um in VB durch die Liste zu navigieren. Die Verweiszeiger von C++ kannst du in VB jedenfalls nicht verwenden. Einen Array solltest du zurückgeben können.



  • Vielen Dank

    d.h vorher auf ein Array konvertieren..das dürfte kein Problem sein.

    bzgl. direkten Zugriff auf das Array, welches in C++ erzeugt wird - Nur Umweg über Rückgabe des Arrays - Funktion an VB möglich oder?
    😕



  • Hallo

    bräuchte leider schon wieder deine Hilfe

    Dieses Mal ist soll die Variant Variable kein Array sein sonder nur ein Wert.

    STDMETHODIMP CAlgo::Add(VARIANT *variant_element)
    {
    
    	defDataType(variant_element);
    
    	//insertElementBegin(value, &listB, &listE);
    
    	//Quicksort_int(array_int, 0, nCount);
    
    	return S_OK;
    }
    
    //
    // defDataType
    // Datentyps des Elements bestimmen/definieren
    //
    
    int defDataType (VARIANT *variant_element) 
    {
    		//.vt = variant type
    		switch (variant_element[0].vt)
    		{
    
    			//Integer
    			case VT_I2:
    			{
    				//array_int[i] = variant_element.iVal;
    				break;
    			}
    ....
    

    ->> Speicherzugriffsfehler

    108:          switch (variant_element[1].vt)
    109:          {
    012B1888   mov         eax,dword ptr [ebp+8]
    012B188B   xor         ecx,ecx
    012B188D   mov         cx,word ptr [eax+10h]  ----> FEHLER
    

    Wie kann ich auf die Variant Variable nun zugreifen? bzw. ist es überhaupt möglich?

    also nun wird in VB ein belieber Wert übergeben (VB konvertiert selbst) und in C++ DLL wird der Datentyp als Variant angenommen und dann guck ich nach welcher Typ das nun ist und arbeite mit dem weiter.

    Vielen Dank! 🙄



  • c147258 schrieb:

    switch (variant_element[0].vt)
    [später]
    switch (variant_element[1].vt)

    Irgendwie passt der Code hier nicht zusammen. Hast du den Code geändert und dann nicht kompiliert? Oder hast du den falschen Code geändert?



  • MFK schrieb:

    Irgendwie passt der Code hier nicht zusammen.

    Ja, wurde geändert, aber egal ob nun 1 oder 0 drinnen steht - Speicherzugriffsfehler - "Die Anweisung in "0x012b185d" verweist auf den Speicher in "0x0000004"." ... Danke



  • Wie sieht die Deklaration von Add aus (.idl oder attributiert)?
    Wie rufst du die Funktion in VB auf?



  • Hallo, danke für deine Hilfe - ich hoffe du meinst das: Algo.h

    Auszug aus Algo.h

    // IAlgo
    public:
    	STDMETHOD(Sort)(/*[in,out]*/ SAFEARRAY **psaArray);
    	STDMETHOD(Add)(VARIANT *variant_element);
    	};
    
    #endif //__ALGO_H_
    

    Auszug test.h

    #if defined(__cplusplus) && !defined(CINTERFACE)
    
        MIDL_INTERFACE("A4294808-2FFE-4311-9EFA-21720C87BA23")
        IAlgo : public IDispatch
        {
        public:
            virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Sort( 
                /* [out][in] */ SAFEARRAY __RPC_FAR * __RPC_FAR *psaArray) = 0;
    
            virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Add( 
                /* [in] */ VARIANT __RPC_FAR *variant_element) = 0;
    
        };
    
    #else 	/* C style interface */
    

    Auszug test.idl

    ]
    	interface IAlgo : IDispatch
    	{
    		[id(2), helpstring("Methode Sort")] HRESULT Sort([in,out] SAFEARRAY(VARIANT) *psaArray);
    		[id(3), helpstring("Methode Add")] HRESULT Add([in] VARIANT *variant_element);
    	};
    

    Aufruf in VB

    Private Sub Command1_Click()
        Dim objAlgo As Algo
        Dim wert As Integer
        Dim i As Long
    
        'Set wert = Text1
         wert = 3
    
         Set objAlgo = New Algo
          objAlgo.Add wert
    

    Danke 😕



  • Problem gelöst...jedoch schon wieder ein neues:

    VB: Funktion von der C++ DLL wird aufgerufen und es wird ein Wert übergeben - jedoch sollte dann auch die Var return_var einen Wert von der FKT zurückbekommen...tuts aber nicht 😞

    ' Output:
        Dim szOutput As String
        Dim count As Variant
    
        szOutput = "Output:"
    
        Dim return_var As Variant
        For count = 0 To 3
        return_var = objAlgo.Key(count)
        szOutput = szOutput & " " & return_var
       Next
    
      MsgBox szOutput
    

    C++ DLL:
    ALGO.CPP

    //
    // Key
    // Bestimmung des Datentyps des Arrays, welches 
    // zuvor in einer Liste abgespeichert wurde
    //
    
    STDMETHODIMP CAlgo::Key(VARIANT *variant_key_in, VARIANT *variant_key_ret)
    {
    	switch(defDataType(&listB->data))
    	{
    		case etInteger:
    			//Integer 
    			 variant_key_ret->iVal = array_int[variant_key_in->iVal];
    			  break;
    		default: break;
    	}
    
    	return 0;
    }
    

    test.idl

    [id(4), helpstring("Methode Key")] HRESULT Key([in] VARIANT *variant_key_in, [retval][out] VARIANT *variant_key_ret);
    

    Algo.h

    STDMETHOD(Key)(VARIANT *variant_key_in, VARIANT *variant_key_ret);
    

    test.h

    virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Key( 
                /* [in] */ VARIANT __RPC_FAR *variant_key_in,
                /* [out][retval] */ VARIANT __RPC_FAR *variant_key_ret) = 0;
    

    Bekomme den genwünschten Wert nicht zurück, obwohl wenn ich es debugge der Wert in der C++ Fkt umgeschrieben wird - jeodch nicht ins VB zurück 😞

    Danke



  • Es reicht nicht, mur den für den Typ passenden Wertmember zu setzen. Du musst auch den Typmember vt setzen.

    Am Einfachsten geht das mit den Hilfsklassen für Variants. die kümmern sich um all das und haben Konstruktoren für praktisch alle VARIANT-Datentypen.

    case etInteger:
    {
        CComVariant var(array_int[variant_key_in->iVal]);
        var.Detach(variant_key_ret);
        break;
    }
    


  • Danke

    hab es eingebunden - jedoch Fehler - fehlt mir noch irgendeine Header Datei oder ähnliches?

    ....Algo.cpp(111) : error C2361: Initialisierung von 'var' durch 'default'-Marke übersprungen
    ......\Algo.cpp(108) : Siehe Deklaration von 'var'
    Fehler beim Ausführen von cl.exe.

    so funkts jedoch:

    variant_key_ret->iVal = array_int[variant_key_in->iVal];
    			variant_key_ret->vt = 2;
    

    Aber trotzdem wäre das andere sicherlich eine bessere Lösung, bitte um "Aufklärung"
    😃



  • c147258 schrieb:

    hab es eingebunden - jedoch Fehler - fehlt mir noch irgendeine Header Datei oder ähnliches?

    Vermutlich hast du die geschweiften Klammern im case-Block nicht übernommen. Wenn die fehlen, darfst du dort keine neuen Variablen definieren.



  • MFK schrieb:

    Vermutlich hast du die geschweiften Klammern im case-Block nicht übernommen.

    Jop..das wars..Danke!

    werd mich nun auf die String konvertierung "lehnen"....



  • Hätte einen Code, welchen ich von einem Programm übernommen habe, jedoch verstehe ich den Sinn nicht ganz, da erst ab dem 4ten Element reingeschrieben wird - dies hat sicherlich einen Grund aber welchen?
    (evtl. Sicherheit bzgl. Speicherüberschreibung?
    single hätte auch 4 Byte)

    /*
     * Konvertiert einen übergebenen BSTR nach (char *).
     * Der Speicher muß von der aufrufenden Funktion freigegeben werden
     */
    char *GetLongBstr(BSTR str)
    {
    	static unsigned char *v;
    	unsigned short i;
    	unsigned short size;
    
    	// Länge feststellen
    	size = SysStringLen(str);
    	v = new unsigned char[size+5];
    	*(int*)v = size;
    
    	// Kopieren
    	for(i=0; i<size; ++i) v[i+4] = (unsigned char)(((unsigned short *)str)[i]);
    
    	// End markieren
    	v[i+4] = 0;
    
    	// Zeiger auf den String (ohne Längenangabe)zurückgeben
    	return (char*)v;
    }
    


  • *(int*)v = size;
    

    Weil er da wohl die Stringlänge reinschreibt. 😉



  • Ja, aber warum fängt er dann nicht mit den 0ten Element an?

    Der erste Buchstabe hat Index(4) ....warum nicht Index(0) ?

    Danke



  • Hallo hätte wieder eine Frage:

    VB Programm aufruf:

    Dim feld(0 To 3) As Variant
       Set objAlgo = New Algo
    
       feld(0) = 4
       feld(1) = 2
       feld(2) = 3
       feld(3) = 1
       objAlgo.Add feld
    

    Jetzt müsste ich unter C++ DLL das Array übergeben. Problem ist jedoch das die Funktion/Schnittstelle Add auch Werte wie Integer und Strings übergeben werden können, und somit fordert die FKT Add einen VARIANT Datentyp. Ist dies nun möglich das ich das Feld an den Variant Datentyp übergebe und später die Daten auslese oder ist es nur mit dem von dir geschriebenen SafeArray(www.overclockers.at) möglich? (Funktion muss gleich heißen!)

    Wenn ich die ADD Funktion mit einem anderen zu erwartenden Parameter hinschreibe, dann kommt jedes Mal redefinition von Add.

    Wäre um jede Hilfe dankbar...



  • Passing an array from VC++ DLL to VB
    http://www.codeproject.com/dll/ctovbarray_passing.asp


Anmelden zum Antworten