Frage zu DLL.... C <-> C++
-
Hi,
ich habe eine (MFC-)DLL die ein C-Interface bereit stellen soll. Die nach außen öffentlichen Funktionen hab ich dabei mit extern "C" kenntlich gemacht. Reicht das aus, damit man die dann auch tatsächlich als C Interface benutzen kann ?
In der Implementierung der Funktionen benutze ich z.B. auch eigens für diese DLL geschriebene Klassen, aber das sollte keine Probleme bereitstellen oder ?
-
extern "C" reicht natürlich noch nicht aus... damit wird eine Funktion *nicht* in der DLL exportiert!
Du musst entweder eine DEF-Datei erzeugen, indem Du die Funktionen explizit aufführst, welche Du zur Verfügung stellen willst; oder Du verwendest ein "__declspec(dllexport)" (was aber "unschöne" Namen erzeugt; also ich rate hiervon ab).
PS: Bei den Parametern/Rückgabewerte der Funktionen solltest Du darauf achten, dass sie keine Abhängigkeiten zu irgendeiner CRT-DLL haben; sonst könnte es da diverse Probleme geben... also kein FILE*, std::string oder sonstwas CRT-mässiges übergeben; nur "Grunddatentypen"...
-
Hi,
danke erst mal für die schnelle Antwort. Dass das alleine für den Export nicht ausreicht war mir schon klar; mir ging es eben nur darum ob ich sonst noch irgendwelche speziellen Dinge beachten muss, damit das auch wirklich ein C Interface bleibt.Wenn ich das dann richtig verstehe, kann ich in der Implementation der Funktion auch Klassen usw. benutzen, solange die Rückgabewerte und Parameter C-konform sind, richtig ?
-
Was Du in der Implementierung machst ist eigentlich vollkommen wurst.
Du musst aber wirklich darauf achten, dass Du nur "Grunddatentypen" verwendest und niemals Dinge aus der MS-CRT (wie eben FILE* oder sonstige CRT-spezifischen Dinge). Auch darfast Du nie in der DLL Speicher allokieren, welcher ausserhalb der DLL freigegeben werden soll. Für das freigeben musst Du dann auch eine Funktionexportieren, welche dann aufgerufen werden muss.Das besten Beispiel für eine "reine" C-DLL ist die gesamte WinAPI.
-
Mh noch eine Frage...
Wie macht man das denn eigentlich am geschicktesten wenn man eben mehrere C-Funktionen als Interface anbietet, aber diese Funktionen intern ein gemeinsames Klassenobjekt benutzen ? Ich hab das bei mir bis jetzt so gemacht://Interface.h //Den DLL-"Overhead" hab ich der Einfachheit halber weggelassen MyClass* object = NULL; extern "C" { void startFunc(); void func1(); void func2(); void endFunc(); }//Interface.cpp void startFunc() { if (object == NULL) object = new MyClass(); //Hier was damit tun } void func1() { if (object != NULL) { //hier was mit object machen } } usw... void endFunc() { if (object != NULL) { delete object; object = NULL; } }Funktionieren tut das so...aber vielleicht gibts da noch bessere Möglichkeiten ?
-
Du übergibst nach extern ein "HANDLE"...
z.B.
typedef void* MyHandle; MyHandle init(); int func1(MyHandle handle); double func2(MyHandle handle); void deinit(MyHandle handle)Und intern verwendest Du das "MyHandle" dazu dieses zur "Klasse" zu casten.
Aber eigentlich solltest Du Deine Funktionen gleich so machen:
typedef DWORD MyResult; #define MYDLL_S_OK 0 #define MYDDL_E_INVALID_HANDLE // ... typedef void* MyHandle; MyResult init(MyHandle *pHandle); MyResult func1(MyHandle handle, int *pOutInt); MyResult func2(MyHandle handle, double *pOutDouble); MyResult deinit(MyHandle handle)Und das ganze am besten noch mit SAL:
http://blogs.msdn.com/michael_howard/archive/2006/05/19/602077.aspx
http://msdn2.microsoft.com/en-us/library/ms235402.aspx=>
typedef DWORD MyResult; #define MYDLL_S_OK 0 #define MYDDL_E_INVALID_HANDLE // ... typedef void* MyHandle; MyResult init(__out MyHandle *pHandle); MyResult func1(__in MyHandle handle, __out int *pOutInt); MyResult func2(__in MyHandle handle, __out double *pOutDouble); MyResult deinit(__in MyHandle handle)
-
Mh also ich hab mir die Links jetzt nicht angeschaut... aber ist das nicht so, dass dadurch die Funktionen anders von außerhalb aufgerufen werden müssen, oder bleibt das so trotzdem gleich ?
-
Bzg. SAL ändert sich von aussen gar nichts.... so wurde z.B. das gesamte SDK jetzt mit SAL Kommentaren versehen... hat sich jetzt dadurch das SDK geändert?