c++ Dll Array an VBA
-
Hallo,
danke das hat sehr gut funktioniert.
-
Hallo,
eine Frage noch mit Safearray funktioniert es jetzt Perfekt.
ich erstelle ein DLL, wenn ich diese dann in VBA aufrufe funktioniert es auch.
Wenn ich aber z.B. Folgende Funktion noch mitrein packe:#include "libpq-fe.h" ... /* Close connection to database */ void CloseConn(PGconn *conn) { PQfinish(conn); getchar(); exit(1); }
Dann bekomme ich in VBA die Laufzeitfehler 53, dass mein DLL nicht gefunden wird. woran kann das liegen?
-
*Glaskugel-guck*
Daran dass deine DLL durch das Einbinden der "libpq-fe.h" jetzt eine weitere DLL benötigt, und diese weitere DLL nicht gefunden werden kann.
Und das wiederrum...
*Glaskugel-polier*
*Glaskugel-guck*...liegt daran dass du deine DLL irgendwo liegen hast, wo sie auch registriert ist und alles toll, und die andere DLL auch im selben Verzeichnis. Und das VB Programm in irgend einem anderen Verzeichnis.
Windows findet nun deine DLL über den in der Registry abgespeicherten Pfad. Sieht dann dass deine DLL noch eine weitere braucht, und versucht die dann auch zu laden. Und dabei guckt Windows eben NICHT in dem Verzeichnis deiner DLL.
-
Hallo,
gibt es den eine andere Lösung als immer alle Dlls, die für die Datenbankverbindung gebraucht werden in dem gleichen Ordner zu haben?
Ich war so nah an Ziel?
Hab ich dann das ganze umsonst gemacht, wenn ich die Dll nicht verschieben kann?
-
borhan schrieb:
Hallo,
gibt es den eine andere Lösung als immer alle Dlls, die für die Datenbankverbindung gebraucht werden in dem gleichen Ordner zu haben?
Naja, wenn es um "statische" DLL-Importe geht, dann muss Windows die DLLs finden können. Wo überall gesucht wird kannst du dir ja ergoogeln.
Ansonsten kannst du die andere DLL natürlich dynamisch laden. Da kannst du dann den vollständigen Pfad angeben. Dann musst du dir aber auch alle Funktionsadressen "manuell" holen, also mit GetProcAddress. Oder rumtricksen.
Ich war so nah an Ziel?
Ist das wirklich eine Frage?
Hab ich dann das ganze umsonst gemacht, wenn ich die Dll nicht verschieben kann?
Weiss nicht. Was willst du denn überhaupt machen?
-
Nee, Das war keine Farge. Ich bin jetzt seit mehr als zwei Wochen dran und ich habe es mit DLL nicht probiert und jetzt kommt sowas.
Was meinst du mit rum tricksen?
-
Die DLL mit
/DELAYLOAD
linken, und dann vor dem ersten Zugriff auf eine DLL Funktion manuellLoadLibrary
mit dem richtigen Pfad machen.Soweit ich weiss lädt Windows immer nur eine DLL pro Filename (exklusive Pfad!). Ein zweites LoadLibrary mit dem selben Filenamen gibt dann einfach die bereits geladenen DLL zurück.
Hab's noch nicht probiert, aber müsste mMn. funktionieren.
Tip: an den vollständigen Pfad zu deiner DLL kommst du mit
GetModuleFileName(moduleHandleDeinerDLL, ...)
.
Und an das Module-Handle deiner DLL kommst du z.B. durchGetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)(AdresseInDeinerDll), &hmodule)
.
Bzw. ich meine das ist auch das selbe wie inDllMain
alsHINSTANCE
mitgegeben wird.Alternativ könntest du
AddDllDirectory()
verwenden. Gibt's halt erst am Win8...
-
Hallo,
danke für dein Antwort. Also:
#include <string> #include "C:\Program Files (x86)\PostgreSQL\9.2\include\libpq-fe.h" #include <iostream> #include <windows.h> #include <comutil.h> ... #pragma comment(linker, "/DelayLoad:libpq.dll") ... void CloseConn(PGconn *conn) { PQfinish(conn); getchar(); exit(1); }
Wo muss ich jetzt die Dll wieder aufrufen?
-
Ich habe ein schönen Beitrag gefunden auf der Seite http://www.codeguru.com/cpp/cpp/cpp_mfc/tutorials/article.php/c9855/DLL-Tutorial-For-Beginners.htm
Was mir aber noch unklar ist:
Also:typedef int (*AddFunc)(int,int);
Ich bentöige aber als Parameter nicht int sondern ein Typ, der auch in der DLL defeniert ist. Wie kann man das den lösen?
-
Achje, das wird mir etwas zu mühsam hier.
Mit anderen Typen geht es genau so. Und damit die bekannt sind, musst du halt das Header-File includen. Evtl. diverse
#pragma comment(lib
entfernen damit nicht automatisch das .lib File der DLL gelinkt wird.
-
HAllo,
danke dass du trotzdem antworteset. Ich habe einfach die Path- Variable angepasst. Ansonsten habe ich hierzu keine Fragen mehr!
Allerdings habe ich eine Frage zum Verständnis. Wenn ich mein Dll- Funktion aus VBA aufrufe dann muss ich noch ein ALIAS Name mit angeben
#if defined(_MSC_VER) //#include <windows.h> #define DLL extern "C" __declspec(dllexport) #else #define DLL #endif //mein Funktion in der DLL int add(int a,int b) ...
Aufruf in VBA :
Public Declare Function FUNKTIONSNAME Lib "Pfad" Alias _FUNKTIONSNAME@8
und 8 Weil ich zwei Parameter habe. Wenn ich jetzt drei hätte wären es 12.
Gibt es vielleicht eine Möglichkeit, den Alias Name wegzulassen?
-
Von VBA hab' ich nicht viel Plan.
Was sicher geht (aber, falls du es noch nicht hast, vermutlich auch viel Aufwand ist): COM Klassen statt freien Funktionen in der C++ DLL implementieren.
In VBA kannst du das dann gleich verwenden wie z.B. das "FileSystemObject" oder ähnliche Utility-Klassen.
ps:
Du kannst in der C++ DLL extern "C" verwenden wenn du das @8 etc. weghaben willst.__declspec(dllexport) void Foo(int a, int b); // _Foo@8 __declspec(dllexport) extern "C" void Bar(int a, int b); // Bar (oder _Bar, weiss ich ehrlich gesagt nicht auswendig)
Und es kann sein dass das
extern "C"
vor das__declspec(dllexport)
gehört - diese Dinge merk ich mir nie.
-
Ich habe leider nur visual Studio Express, deswegen kann ich die COM Klassen nicht verwenden. Aber ALisname hat ja damit zutun, dass in der DLL die FUnktion ja diesen Namen hat also _FUnktionsname@Speicher! Kann man den diese Namenskonvertierung nicht umgehen?
-
Ja. Siehe das "ps".
-
Hallo,
danke für dein Antwort. Der Rest funktioniert jetzt alles. Danke.
Ich bekomme aber immer noch _Funktionsname@8 nicht weg.
Ich habe es auch mit extern "C" versucht. Erst mit extern "C" funktioniert die obere Schreibweise.
-
Ah, ja, richtig, mit
__stdcall
ist das so.
Naja, du kannst noch .def Files verwenden.
-
Hallo,
was würde mir denn .def bringen. Kann ich den da sagen, dass ich die Endung weghaben möchte