[C++] dll's

pcw

Lt. Commander
Dabei seit
Juli 2001
Beiträge
1.658
[c++] dll's

Also ich sitz hier jezz scho den ganzen Tag und versuch mich durch diese dummen c++ Tutorials zu wühlen und rauszufinden, wie man eine dll programmiert, die man auch unter anderen compilern oder gar delphi etc benutzen kann.

Ich kann zwar die DLL erstellen, aber irgendwie lässt sich keine Funktion daraus aufrufen bzw sie sind nie exportiert worden.

Die Dll will/muss ich mit Borland CBuilder6 erstellen und aufrufen können würd ich sie gern in ner Konsolenanwendung, die ich mit Borland C++ 5 (oder Delphi6) geschrieben hab...

Kann mir wer kurz ein Grundgerüst dafür geben?
 

pcw

Lt. Commander
Ersteller dieses Themas
Dabei seit
Juli 2001
Beiträge
1.658
Re: [c++] dll's

ich bekomm immer ein

[Linker Error] Unresolved external 'addiere(int, int)' referenced from F:\PROGRAMME\BORLAND\CBUILDER6\PROJECTS\ANIOU\DATABASE\UNIT1.OBJ

zurück...

und in delphi schreib ich sie ned, weil ich c++ lernen will.
 

7H3 N4C3R

Lt. Commander
Dabei seit
Feb. 2002
Beiträge
1.816
Re: [c++] dll's

Huh... ein Linker-Fehler? Das klingt aber mal ziemlich eigenartig...
Also lässt sich die DLL garnicht erst compilieren?

Kannst Du mal nen Code-Schnipsel posten?
 

pcw

Lt. Commander
Ersteller dieses Themas
Dabei seit
Juli 2001
Beiträge
1.658
Re: [c++] dll's

die dll (lässt sich kompilieren udn ich hab auch schon andere funktionsschreibweisen für den dll-export probiert)
Code:
int __declspec(dllexport) addiere(int zahl1,int zahl2);
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
        return 1;
}

int addiere (int zahl1,int zahl2)
{
 return zahl1+zahl2;
}
die Konsolenanwendung (lässt sich ned kompilieren)
Code:
extern int __declspec(dllimport) addiere(int zahl1,int zahl2);

#pragma argsused

int main(int argc, char* argv[])
{
        int summe = addiere(5,6);
        cout<<summe;
        system("PAUSE");
        return 0;
}
 

7H3 N4C3R

Lt. Commander
Dabei seit
Feb. 2002
Beiträge
1.816
Re: [c++] dll's

Mmmh woher weiß der Compiler da, welche DLL er importieren muss?
Ich bevorzuge generell das dynamische Importieren, da dann das Programm nicht mit einer obskuren Fehlermeldung abstürzt, wenn es die DLL nicht findet. Mal ein kleiner Beispielcode in Delphi: (sollte ganz einfach nach C++ zu konvertieren sein, hab nur den C++-Builder net auf diesem Rechner)

Code:
uses
  SysUtils, Windows;

type
  TAddiereFunc = function (Zahl1: Integer; Zahl2: Integer): Integer; stdcall; 
  // immer stdcall verwenden, außer Du hast es anders angegeben
  // beim Export von Funktionen aus Delphi auch am Besten immer stdcall verwenden

var
  hDLL : Cardinal;
  add  : TAddiereFunc;
  PTest: Pointer;

  x    : Integer;
begin
  hDLL := LoadLibrary ('deineDLL.dll'); // name ersetzen ;)
  if hDLL = 0 then
  begin
    WriteLn (SysErrorMessage (GetLastError));
    Exit;
  end;

  try
    PTest := GetProcAddress (hDLL, 'addiere'); // auf Groß/-Kleinschreibung achten
    if not Assigned (PTest) then
    begin
      WriteLn (SysErrorMessage (GetLastError));
      Exit;
    end;

    @add := PTest;
    x := add (5, 6);
    WriteLn ('5 + 6 = ', x);
  finally
    CloseHandle (hDLL);
  end;
end.
 
Zuletzt bearbeitet:

pcw

Lt. Commander
Ersteller dieses Themas
Dabei seit
Juli 2001
Beiträge
1.658
Re: [c++] dll's

ich delphi kann ich das.

aber wie geht das in c++ ?
 

7H3 N4C3R

Lt. Commander
Dabei seit
Feb. 2002
Beiträge
1.816
Re: [c++] dll's

Hmm naja, analog würde ich annehmen =) Ich versuchs einfach mal, ohne Garantie auf Kompilier/Lauffähigkeit...

Code:
typedef int (WINBASEAPI WINAPI *Addiere)(int zahl1, int zahl2);

#include <cassert>
#include <iostream>

using namespace std;
....

HMODULE hMod = LoadLibrary ("meine.dll");
assert (hMod);
Addiere addiere = reinterpret_cast<Addiere>(GetProcAddress (hMod, "addiere"));
assert (addiere);
cout << addiere (5, 6);
CloseHandle (hMod);
Btw, das Delphi-Beispiel war mehr dafür gedacht, um rauszuinden, ob der Export auch funktioniert.
 
Zuletzt bearbeitet: (Änderung des Funktionsprototypen)

pcw

Lt. Commander
Ersteller dieses Themas
Dabei seit
Juli 2001
Beiträge
1.658
Re: [c++] dll's

So, Problem gelöst!

Aber anders, als du geschrieben hast. Da hat er mir nämlich imerm irgend nen Fehler ausgegeben.

Im Endeffekt musste ich bloß im Projektmenü die DLL-Unit zum Projekt hinzufügen udn nu geht es ;)

der Code:

Code:
extern "C" __declspec(dllimport) addiere(int zahl1,int zahl2);
#pragma argsused

int main(int argc, char* argv[])
{
cout << addiere (5, 6);
        system("PAUSE");
        return 0;
}
 

7H3 N4C3R

Lt. Commander
Dabei seit
Feb. 2002
Beiträge
1.816
Re: [c++] dll's

Mmh was meinst Du mit "Unit"? Die Cpp-Datei? Damit lädst Du aber keine DLL an...
 

pcw

Lt. Commander
Ersteller dieses Themas
Dabei seit
Juli 2001
Beiträge
1.658
Re: [c++] dll's

Joah, aber Borland macht das dann automatisch.

Andere Frage:

Ich will eine Funktion aus einer vorhandenen DLL aufrufen ohne irgendeine Sourcedatei der DLL zu haben. Wie muss ich vorgehen?
 

7H3 N4C3R

Lt. Commander
Dabei seit
Feb. 2002
Beiträge
1.816
Re: [c++] dll's

In deinem Fall ist der Code einfach in Deine Exe reinkompiliert, als wenn Du irgendeine Unit einbindest.

Wenn Du eine DLL benutzt, benutzt Du nie den realen Sourcecode, sondern eine kompilierte Bibliothek.


Willst Du die DLL denn statisch oder dynamisch laden? Im ersten Fall generiert der Compiler alle Anweisungen, um eine DLL zu laden. Das passiert aber bereits zu Programmstart und gibt die 'schönsten' Fehlermeldungen, falls eine DLL nicht gefunden wird. Im zweiten Fall lädst Du die DLL selbst an, also mit LoadLibrary und GetProcAddress. Das ist die Möglichkeit, die man immer bevorzugen sollte (aber Ausnahmen bestätigen die Regel), zumal es ist die einzige Möglichkeit, wenn man sich z.B. einen Plugin-Loader schreiben will.

Der Code, den ich gepostet habe, sollte zum DLL dynamischem anladen eigentlich völlig ausreichen. Habe wohl anscheinend nur irgendwo nen Fehler gemacht. Werd mir hier mal auch noch den Borland Builder installieren, das Problem interessiert mich jetzt auch :)
 

pcw

Lt. Commander
Ersteller dieses Themas
Dabei seit
Juli 2001
Beiträge
1.658
Re: [c++] dll's

Ich will einfach mit dem CBuilder6 eine DLL schreiben.

Das brauch ich für ne Schulaufgabe.

Da aber unser Lehrer/das OSZ nur BorlandC 5.0 hat und das eigentliche Programm da noch kompilierbar sein muss (war Voraussetzung, dass ich den CBuilder benutzen durfte), muss ich die DLL halt so gestalten, dass ich sie von BorlandC 5.0 aus aufrufen kann.

Die App soll aber trotzdem vollständig in der Konsole laufen. ich will bloß auf ein paar NON-VCL-Komponenten wie TQuery zurückgreifen ;)

In Delphi hab ich das alles schon einwandfrei laufen, aber in C komm ich einfach mit den DLL's ned hin.

kannst du mir einfach mal eine simple DLL machen, in der vcl eingebunden ist und eine Konsolenanwendung in BC5, die eine Funktion aus dieser DLL aufruft?
 

7H3 N4C3R

Lt. Commander
Dabei seit
Feb. 2002
Beiträge
1.816
Re: [c++] dll's

kannst du mir einfach mal eine simple DLL machen, in der vcl eingebunden ist und eine Konsolenanwendung in BC5, die eine Funktion aus dieser DLL aufruft?
Werd ich versuchen, kann allerdings ein wenig dauern, da ich auch noch an einem Referat arbeiten muss :(

Ich habe bis jetzt aber leichte Bedenken wegen dem Einbinden der VCL über eine DLL in eine Non-VCL-Anwendung. Wenn ich was rausfinde, werd ich's aber auf jeden Fall posten ;)
 

7H3 N4C3R

Lt. Commander
Dabei seit
Feb. 2002
Beiträge
1.816
So okay, ich hab's jetzt bei mir funktionierend hinbekommen. Problem war, dass ich das extern "C" vergessen hatte. Damit wird das C++-Namemangeling durchgeführt und der Funktionsname ist quasi nicht mehr zu "erraten". Gibt man aber anstatt dem Funktionsnamen einen Index an, gehts aber auch.

DLLSource:
Code:
#include <windows.h>

extern "C" _declspec(dllexport) int Addiere (int zahl1, int zahl2)
{
	return zahl1 + zahl2;
}

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
    switch (ul_reason_for_call)
	{
		case DLL_PROCESS_ATTACH:
		case DLL_THREAD_ATTACH:
		case DLL_THREAD_DETACH:
		case DLL_PROCESS_DETACH:
			break;
    }
    return TRUE;
}
Testprogramm:
Code:
#include <cstdlib>
#include <iostream>
#include <windows.h>

using namespace std;

typedef __declspec(dllimport) int (*Addiere)(int zahl1, int zahl2);

int main(int argc, char* argv[])
{
	HMODULE hMod = LoadLibrary ("W:\\cppdll.dll");
	if (hMod)
	{
		void* farproc = GetProcAddress (hMod, "Addiere");
		if (farproc)
		{
			Addiere addiere = reinterpret_cast<Addiere>(farproc);

			cout << "5+6=" << addiere (5, 6) << endl;
		}
		else
			cout << "Fehler bei GetProcAddress" << endl;
		FreeLibrary (hMod);
	}
	else
		cout << "Fehler bei LoadLibrary" << endl;

	system ("pause");
	return 0;
}
 
Zuletzt bearbeitet:

pcw

Lt. Commander
Ersteller dieses Themas
Dabei seit
Juli 2001
Beiträge
1.658
Also ich hab ne Variante, die funktioniert, aber Borland C++5.0 hat nen Bug, weswegen man damit keine DLL's benutzen kann, ohne dass es windowsfehler gibt...

ziemlicher müll, weil ich BC5 ja nur wegen der schule benutzen muss und die das entsprechende patch ned installieren wolln :-/
 
Top