C++ DLL in Excel VBA 2010 mit 64 bit



  • Hallo Freunde,

    ich bin nun gezwungen auch mal auf Excel 2010 umzusteigen. Leider habe ich da erhebliche Probleme mit meinen erstellten Programmen. Die 32 bit DLLs laufen alle unter Excel 2010 nicht mehr...

    Allgemein haben wir das Problem hier gelöst: http://www.c-plusplus.net/forum/318786

    Nun brauche ich das ganze für Excel 2010.

    Minimalbeispiel:

    C++:

    using namespace std;
    
    extern "C" __declspec(dllexport) int __stdcall square(double zw){
    
    	zw = 5^2;
    
    	return 0;
    }
    

    mit dem Def-File:

    LIBRARY "square"
    EXPORTS
    square
    

    in VBA der Funktionsaufruf:

    Declare PtrSafe Function square Lib "E:\C++\square_x64\Release\square_x64.dll" (ByVal zw As Long) As Long
    
    Sub test()
    
        Dim zw As Double
    
        Call square(zw)
    
        MsgBox zw
    
    End Sub
    

    Es kommt als Rückgabewert leider nur "0", aber keine Fehlermeldung.

    Im Compiler und Linker wird mit 64 bit compiliert, also ohne "-m32":

    "g++ -O3 -Wall -c -fmessage-length=0"

    Der Term "PtrSafe" in VBA ist entsprechend http://msdn.microsoft.com/de-de/library/office/ee691831(v=office.14).aspx neu.

    Muss ich noch etwas anders beachten? Was mache ich falsch, wo liegt der Fehler??? Komme gerade absolut nicht weiter...

    Bin für jeden Tip dankbar!

    Grüße



  • ootobbyoo schrieb:

    return 0;
    

    Es kommt als Rückgabewert leider nur "0"

    Versteckte Kamera?



  • Der Rückgabewert wird aber gar nicht benutzt.
    Der eigentliche Fehler ist, daß die lokale Variable zw innerhalb der C-Funktion zwar einen Wert zugewiesen bekommt, aber da dies nur eine Kopie ist (Stichwort: call by value), wird die originale Variable zw (aus dem VBA-Code) nicht geändert.

    Am besten also den geänderten Wert wieder zurückgeben, d.h.

    extern "C" __declspec(dllexport) double __stdcall square(double zw)
    {
        zw = 5^2;
    
        return zw;
    }
    

    Und dann von VBA aus so aufrufen

    Sub test()
    
        Dim zw As Double
    
        zw = Call square(zw)
    
        MsgBox zw
    
    End Sub
    

    Sinn macht die Übergabe des Wertes natürlich nur, wenn dieser auch irgendwie innerhalb der C-Funktion verwendet wird, also z.B. zw += 42.

    PS. 5^2 ist 7, nicht 25 (nur falls du dich über das Ergebnis wunderst 😉



  • Und...

    Declare PtrSafe Function square Lib "E:\C++\square_x64\Release\square_x64.dll" (ByVal zw As Long) As Long
    

    VBA "Long" != C++ "double"
    =>

    Declare PtrSafe Function square Lib "E:\C++\square_x64\Release\square_x64.dll" (ByVal zw As Double) As Double
    


  • Hallo Leute,

    viele Dank für euch Hilfe. Musste es noch ein wenig verändern, aber so klappt es:

    C++:

    extern "C" __declspec(dllexport) double __stdcall square_x64(double b){
    
    	double zw;
    
    	zw = b*b;
    
    	return zw;
    }
    

    VBA:

    Declare PtrSafe Function square_x64 Lib "E:\C++\square_x64\Release\square_x64.dll" (ByVal zw As Double) As Double
    
    Sub test()
    
        Dim zw As Double
    
        zw = square_x64(5)
    
        MsgBox zw
    
    End Sub
    

    Leider bin ich damit noch nicht ganz am Ziel. Im Grunde möchte ich das ganze mit einem 2D-Array machen. Diesen gebe ich von VBA an C++, dort wieder dieser verändert und ich gebe diesen wieder zurück an VBA. In dem Beitrag http://www.c-plusplus.net/forum/318786 hatte ich das für Excel 2003 schon einmal gelöst. Habt ihr da für die 2010er Version mit 64 bit eine Idee???

    VIELEN DANK



  • Müsste in etwa so aussehen:

    extern "C" __declspec(dllexport) double __stdcall square_x64(double zw[][2]){
    
    	zw[5][1] = 3;
    	zw[3][2] = 4;
    
    	return 0;
    }
    

    VBA:

    Declare PtrSafe Sub square_x64 Lib "E:\C++\square_x64\Release\square_x64.dll" (ByVal zw As Double)
    
    Sub test()
    
        Dim zw(1 To 5, 1 To 2) As Double
    
        Call square_x64(zw)
    
        MsgBox zw(5, 1) 'sollte dann 3 sein
        MsgBox zw(3, 2) 'sollte dann 4 sein
    
    End Sub
    

    Ich nehme mal an als Sub klappt es besser, eine Function hat ja nur ein Wert als Rückgabe. Versuche ich in C++ einen Array zurück zu geben, kommt ein Fehler: "error: cannot convert 'double (*)[2]' to 'double' in return".

    In VBA kommt dann die Fehlermeldung "Typen unverträglich" und das "zw" im Aufruf wird makiert. Irgendwie schein bei der Übergabe wsa nicht zu klappen...?


Log in to reply