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...?