(c++)Probleme beim Verwenden einer Bibliothek in einer Windows Forms Anwendung

SchindlerD

Grünschnabel
Hallo liebe Forenmitglieder!

Vielleicht könnt ihr mir bei einem (für mich) kniffligen Problemchen helfen. Vermutlich mache ich etwas grundlegendes falsch. Ich verwende Visual Studio 2005 und schreibe an einer Windows Forms Anwendung, die später mal Daten loggen soll.
Hm, wie fange ich jetzt am besten an?
Zu meinem AD-Wandler hat der Hersteller (bmcm) eine nette Bibliothek mitgeliefert, die ich natürlich jetzt gerne in meiner Windows Forms Anwendung verwenden würde.
Ich habe mal eine Testapplikation für die Konsole geschrieben, da hat alles wunderbar geklappt.
Schnipsel:
C++:
#include "stdafx.h"
#include "libad.h"       // Header der lib

int _tmain(int argc, _TCHAR* argv[])
{
	int32_t adh;
     //...

	adh = ad_open ("pc20"); // hier wird ein Befehl aus der lib verwendet
     //...
}
Prototyp in der mitgelieferten Headerdatei:
C++:
int32_t
ad_open (const char *name);
Die .lib datei und die mitgelieferten header habe ich zu den Programm-headern und .cpp dateien gespeichert und die .dll zur .exe. Außerdem habe ich die .lib über project/properties/linker/input als additional dependency angegeben (sorry, habe nur die englische Version von VS...).
So weit, so gut. Als nächstes habe ich versucht, das Selbe in einem Windows Forms Projekt hinzubekommen.
Schnipsel:
C++:
#include <cstdlib>
#include "libad.h"
#pragma comment(lib, "libad4.lib")

//...
	private: System::Void timer1_Tick(System::Object^  sender, System::EventArgs^  e) {

				 int32_t adh;

				 adh = ad_open("pc20");   // selber Befehl wie im Konsolen-Programm
//...
}
Leider kriege ich jetzt beim Kompilieren folgende Fehlermeldungen:

Error 1 error LNK2031: unable to generate p/invoke for "extern "C" int __clrcall ad_open(char const *)" (?ad_open@@$$J0YMHPBD@Z); calling convention missing in metadata adiotest.obj

Error 2 error LNK2028: unresolved token (0A000010) "extern "C" int __clrcall ad_open(char const *)" (?ad_open@@$$J0YMHPBD@Z) referenced in function "private: void __clrcall adiotest::Form1::timer1_Tick(class System::Object ^,class System::EventArgs ^)" (?timer1_Tick@Form1@adiotest@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z) adiotest.obj

Error 3 error LNK2019: unresolved external symbol "extern "C" int __clrcall ad_open(char const *)" (?ad_open@@$$J0YMHPBD@Z) referenced in function "private: void __clrcall adiotest::Form1::timer1_Tick(class System::Object ^,class System::EventArgs ^)" (?timer1_Tick@Form1@adiotest@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z) adiotest.obj

Error 4 fatal error LNK1120: 2 unresolved externals
adiotest.exe

Die Kommentare zu den Fehlern unter MSDN helfen mir irgendwie nicht weiter...
Ich habe mir jetzt mal zusammengereimt, dass der Kompiler versucht, die Funktionen über __clrcall aufzurufen - und daran scheitert? Kann man diesen Versuch irgendwie unterdrücken? Für andere Lösungen bin ich natürlich jederzeit offen :)
Natürlich habe ich die .lib wieder zu den headern gepackt. Eine .exe wird aber erst garnicht erstellt, also erübrigt es sich, die .dll irgendwo hin zu speichern.
Zusätzlich zu dieser Bibliothek gibt es noch eine ActiveX Control (inclusive Library) für den Wandler. Könnt ihr mir erklären wozu ich das brauche? Soll ich mal versuchen damit zu arbeiten? Ich dachte ActiveX hätte nur etwas mit der Darstellung zu tun und dafür hätte ich ja die Windows Form?

Vielen Dank schonmal für eure Hilfe!
Liebe Grüße,
SchindlerD
 
Zuletzt bearbeitet von einem Moderator:
Hallo,

Windows Forms ist Managed C++, und das dürfte sich mit den sonst üblichen Import-Bibliotheken (*.lib) schwer tun. Du solltest daher versuchen die DLL dynamisch einzubinden und die einzelnen Funktionen via DllImport hereinholen:
C++:
using namespace System::Runtime::InteropServices;
...
[DllImport("Name_der _DLL.dll")]
extern "C" int ad_open(const char *name);
ActiveX-Komponenten müssen nicht unbedingt immer etwas visualisieren. Sie haben den Vorteil, dass sie von unterschiedlichsten Programmierumgebungen relativ einfach verwendet werden können. Das wäre also auch eine Möglichkeit für dich.

Gruß
MCoder
 
Wunderbar!
Übersetzungsfehler gibt es jetzt schonmal keine mehr. Allerdings weiß ich jetzt nicht recht wie ich den Befehl im Programm verwenden soll.
Wenn ich die Funktion "normal" aufrufe krieg ich den Fehler: "Der Einstiegspunkt ad_open wurde nicht in der DLL libad4.dll gefunden."
Ach, und Danke für die schnelle Antwort!

Da ich jetzt schon öfter Probleme mit diesem managed C++ hatte: Gibts da eigentlich ein gutes Buch (oder sonstige schriftliche Ressourcen) drüber?

Liebe Grüße!
 
Starte doch mal das Programm "Depends" (sollte unter ...\Common7\Tools\Bin beim Visual Studio liegen) und öffne damit deine DLL. In der zweiten Tabelle auf der rechten Seite werden in der Spalte "Funktion" die Namen der exportierten Funktionen angezeigt. Diese musst du dann verwenden. Wahrscheinlich weichen sie von den Namen in der Import-Lib ab.

Da Managed C++ eine Microsoft-Erfindung ist, dürfte das Thema mit allen besseren Visual-Studio-Wälzern erschlagen werden. Aber da kenne ich mich nicht wirklich aus; für mich hat bisher immer die MSDN und was man sonst noch so im Netz findet gereicht :)

Gruß
MCoder
 
Guten Morgen!

Also, ich hab jetzt mal mit diesem Dependency Walker in der .dll gestöbert. Kann es sein, dass darin mehrere .dlls zusammengefasst sind? Wie greife ich dann auf so eine "Unter-dll" zu?

Nachdem ich etwas erschrocken war, weil es doch recht viele Funktionen sind in der .dll, habe ich mir die Doku zu der ActiveX-Version angeschaut. Leider ist die nicht all zu umfangreich. Hauptsächlich wird darin auf Visual Basic eingegangen. Falls es ne allgemeinere Anleitung gibt, wie ich diese .ocx (natürlich in managed code...) einbinden kann , wäre das vielleicht noch ne Alternative... Meine Versuche wurden mal wieder mit Protesten des Kompilers belohnt :rolleyes: Irgendwelche Tips?

Ach ja! Beim Öffnen des Dependency Walkers gibts übrigens Warnungen:
Warning: At least one delay-load dependency module was not found.
Warning: At least one module has an unresolved import due to a missing export function in a delay-load dependent module.
Und in der Tabelle rechts unten (wo die exportierten Funktionen stehen sollten) sind nur N/As zu finden... Ist die .dll kaputt?

mfG
SchindlerD
 
Zuletzt bearbeitet:
Hallo,

der Dependency Walker zeigt alle Abhängigkeiten, also auch alle sonstigen (System-)DLLs die da mit involviert sind. Daher die lange Liste. Die Warnungen sind normalerweise kein großes Problem, da sowas von der DLL gemanaged werden sollte. Die "N/A" bedeuten, dass die Funktionen nur über ihre Ordinal Nummer, aber nicht über ihren Namen exportiert werden. Dann wird's natürlich mit der Zuordnung schwierig, so dass du wohl wirklich auf das OCX ausweichen solltest.
Wie man Managed C++ und OCX zusammenbringt kann ich dir allerdings nicht sagen. Möglicherweise bekommt man es über "Extras" und "Toolboxelemente auswählen" in die Toolbox hinein.

Gruß
MCoder
 
Nach langem Rumprobieren habe ich jetzt entdeckt, dass man die .ocx tatsächlich einfach in die Toolbox ziehen kann. Weiß nur noch nicht ob die importierten Funktionen so gut funktionieren. Kompilieren und laufen tut es, allerdings kriege ich komische Eingangswerte.Da werde ich wohl noch etwas in richtung Hardware forschen...

Jedenfalls nochmal vielen Dank für die Hilfe!

mfG
SchindlerD
 
Zurück