lib erstellen (c++) für c programm
-
Hallo ist es möglich dass ich mir eine lib aus c++ code erstelle die ich dann in meinem c projekt hinzufüge ? hab es mal probiert bekomm aber weiterhin linkerfehler
-
Ja, ist moeglich. Wie hast du es denn probiert?
-
das ist der code für die lib
#include <windows.h> #include <shlobj.h> #include <tlhelp32.h> #include <crtdbg.h> __declspec(dllexport) void __cdecl WinFWBypass(char *appName); HRESULT func2() { } __declspec(dllexport) void __cdecl func1(char *appName) { }
dann in meinem c programm einfach den prototyp bekannt gemacht
int func1(char *appName);
und die erstellete lib im linker angegeben
-
Kann es sein, dass ein
extern "C"
fehlt?
-
ops hab vergessen den einen funktions name zu editieren, nur das keine falschen vermutungen aufkommen es soll keine maleware werden sondern nur ein chat programm was ich für die windows firewall freischalten möchte
-
extern "C" { __declspec(dllexport) void __cdecl func1(char *appName) { } }
einfach dann so ?
-
Ich glaube, es reicht auch, wenn du einen extern "C" Block im Header um die Prototypen packst. Aber probier doch einfach mal. Klappt's?
-
also ohne den extern c block geht es nicht
extern "C" { void func1(char *appName); }
sp bekomme ich syntaxfehler, danke schonmal für die tipps
-
steff' schrieb:
sp bekomme ich syntaxfehler
Es reicht generell nicht, hier einfach zu schreiben, dass du Fehler bekommst. Du musst schon sagen, welche Fehler (genaue Fehlermeldung per Copy&Paste).
Außerdem bin ich nicht sicher, ob du den Däckelspeck beim Prototypen einfach weglassen darfst. Notiere den Prototypen mal genau wie bei der Implementation.
Hier gibt's passende Doku: http://msdn.microsoft.com/en-us/library/z4zxe9k8(v=vs.80).aspx
-
Mal ein vollständiges Beispiel mit Erklärung:
Angenommen, du hast die C++-Funktionvoid cpp_funktion(bool foo, const std::string& bar) { if (foo) std::cout << bar << '\n'; }
Da das aus C sowieso nicht aufrufbar ist, brauchst du erst einmal eine Kompatibilitätsschicht, die dir überhaupt den Aufruf ermöglicht:
void c_kompatible_funktion(int foo, const char* bar) { cpp_funktion(foo, bar); }
Falls deine ursprüngliche Funktion schon C-kompatibel ist, kannst du dir diesen Schritt sparen und gleich mit deiner Originalfunktion so verfahren wie ich im Folgenden mit der Wrapperfunktion verfahre.
C++ hat Funktionsüberladung und andere Sachen die C nicht kennt. Intern wird dies dadurch gelöst, dass die Funktionen hinterher gar nicht mehr ihren eigentlichen Namen haben, sondern auch noch der Typ der Parameter in die Symbolnamen in einer Bibliothek aufgenommen wird ("name mangling"). Ein C-Linker kann die Funktionen daher nicht unter dem Namen finden, den er erwartet. Daher muss die Schnittstellenfunktion so übersetzt werden, dass der Name des Symbols im Output nicht verändert wird. Dazu ist das
extern "C"
da. Wir schreiben uns einen passenden Header:#ifndef HEADER_H #define HEADER_H extern "C" { void c_kompatible_funktion(int foo, const char* bar); } #endif
Da wir faul sind, wollen wir den gleichen Header für C und C++ benutzen, daher ein bisschen Präprozessormagie:
#ifndef HEADER_H #define HEADER_H #ifdef __cplusplus extern "C" { #endif void c_kompatible_funktion(int foo, const char* bar); #ifdef __cplusplus } #endif #endif
Sodann können wir ein C-Programm schreiben:
#include "header.h" int main() { c_kompatible_funktion(123, "Hallo Welt!"); return 0; }
Der C++-Quellcode sieht nun so aus:
#include <iostream> #include <string> #include "header.h" void cpp_funktion(bool foo, const std::string& bar) { if (foo) std::cout << bar << '\n'; } void c_kompatible_funktion(int foo, const char* bar) { cpp_funktion(foo, bar); }
Wie übersetzen wir dies nun?
Erst einmal die C++-Bibliothek erstellen (hier Beispiel mit GCC):g++ cplusplus.cpp -c -o cplusplus.o
Dies erstellt die Objektdatei cplusplus.o mit dem Symbol c_kompatible_funktion und einem wilden Alternativnamen für die ursprüngliche Funktion cpp_funktion. Wir könnten diese Datei in eine Bibliothek packen, mache ich für das Beispiel aber nicht, da Bibliotheken nichts anderes sind als Sammlungen solcher Objektdateien.
Dann übersetzen wir den C-Code:gcc c.c -c -o c.o
Und linken dann alles zusammen. Nicht vergessen, dass die C++-Standardbiblithek mitgelinkt werden muss, sofern diese vom C++-Code benötigt wird!
gcc c.o cplusplus.o -lstdc++ -o fertiges_programm
Die letzten beiden Schritte kann man (beim GCC und vielen anderen Compilern) auch direkt zusammenfassen:
gcc c.c cplusplus.o -lstdc++ -o fertiges_programm
-
Erstmal danke sepp für die super ausführliche antwort. leider haut es bei mir noch immer nicht hin, weiterhin linker fehler. ich mache das ganez aber auch mit VS und nicht mit gcc , vlt liegt es ja daran ? hab in VS die lib dem projekt hinzugefügt und unter linkereinstellungen die lib hinzugefügt. was ich sonst noch machen kann weiss ich nicht..
-
steff' schrieb:
Erstmal danke sepp für die super ausführliche antwort. leider haut es bei mir noch immer nicht hin, weiterhin linker fehler. ich mache das ganez aber auch mit VS und nicht mit gcc , vlt liegt es ja daran ? hab in VS die lib dem projekt hinzugefügt und unter linkereinstellungen die lib hinzugefügt. was ich sonst noch machen kann weiss ich nicht..
Ich wage mal die Diagnose: Es liegt nicht an deinen Werkzeugen, sondern du machst etwas falsch:
_matze schrieb:
Es reicht generell nicht, hier einfach zu schreiben, dass du Fehler bekommst. Du musst schon sagen, welche Fehler (genaue Fehlermeldung per Copy&Paste).
-
Meine c Header sieht so aus
#ifndef FWBP_H #define FWBP_H #ifdef __cplusplus extern "C" { #endif void WinFWBypass(char* appName); int AddPortToNat(int listeningPort,char* localIP); #ifdef __cplusplus } #endif #endif
dann der call ganz normal in der c datei.
meine lib header
#ifdef __cplusplus extern "C" { #endif void WinFWBypass(char* appName); int AddPortToNat(int listeningPort,char* localIP); #ifdef __cplusplus } #endif
die cpp
int AddPortToNat(int listeningPort,char *localIP) { return 1; void WinFWBypass(char *appName) { return; }
Fehlermeldung:
1> Alle Ausgaben sind aktuell.
1>main.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "_WinFWBypass@4" in Funktion "_WinMain@16".
1>main.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "_AddPortToNat@8" in Funktion "_WinMain@16".
1>..\..\fertig\RPC (Reverse Proxy Client)\client.exe : fatal error LNK1120: 2 nicht aufgelöste externe Verweise.erstelle den cpp code als lib und habe diesem auch dem c projekt hinzugefügt