Ahoi,
ich habe hier ein interessantes Phänomen mit Visual Studio Express 2013.
Und zwar erzeuge ich eine DLL in C, die in einem Delphiprogramm
eingebunden wird.
Ich bekomme keine Warnung bzw. keinen Compilerfehler, wenn meine
Funktion im Header nicht korrekt deklariert ist.
Das Einbinden im Delphicode (dort werden auch Parameter übergeben)
funktioniert aber einwandfrei.
foo.h
1
#ifdef __cplusplus
2
#define EXPORT extern "C" __declspec (dllexport)
3
#else
4
#define EXPORT __declspec (dllexport)
5
#endif;
6
7
8
EXPORT char* bar();
foo.c
1
#include "foo.h"
2
3
char* bar(bool var1, int var2, char* var3, double* var4){
Ich kenne Delphi nicht, aber generell kann man aus einer DLL den Header
korrekt extrahieren (z.B. DLLtool). Kann sein, daß Delphi die Header gar
nicht benutzt.
donvido schrieb:> wenn meine Funktion im Header nicht korrekt deklariert ist.
Was ist denn deiner Meinung nach falsch? Wenn du bar() schreibst,
bedeutet das "beliebige Parameter beliebigen Typs". Das ist kompatibel
zu den angegebenen Parametern. Wenn du wirklich "keine Parameter" haben
willst, musst du "bar(void)" schreiben.
Ich denke eher, dass der Compiler dir nichts mitteilt, da du diese
Funktion in diesem Zusammenhang nirgends aufrufst.
Habs mal mit dem VS 2015 getestet.
1
char*bar();
2
3
char*bar(boolvar1,intvar2,char*var3,double*var4)
4
{
5
printf("FOO");
6
returnvar3;
7
};
8
9
intmain()
10
{
11
charx;
12
doubley;
13
14
/* geht */
15
bar(true,1,&x,&y);
16
17
/* geht nicht */
18
bar();
19
}
Beim Aufruf der bar() liefert der Compiler dann:
error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""char *
__cdecl bar(void)" (?bar@@YAPADXZ)" in Funktion "_main".
Für den Compiler sind es wohl "überladene Funktionen" wobei er für bar()
keine Funktionsdefinition finden kann.
Dr. Sommer schrieb:> donvido schrieb:>> wenn meine Funktion im Header nicht korrekt deklariert ist.>> Was ist denn deiner Meinung nach falsch? Wenn du bar() schreibst,> bedeutet das "beliebige Parameter beliebigen Typs". Das ist kompatibel> zu den angegebenen Parametern. Wenn du wirklich "keine Parameter" haben> willst, musst du "bar(void)" schreiben.
Okay, das mit "beliebige Parameter" war mir nicht ganz bewusst. Mich
hats nur gewundert, dass das nichtmal in irgend einer Weise markiert
wurde.
Adam P. schrieb:> Ich denke eher, dass der Compiler dir nichts mitteilt, da du diese> Funktion in diesem Zusammenhang nirgends aufrufst.
Ja, das klingt plausibel. Danke
Adam P. schrieb:> Beim Aufruf der bar() liefert der Compiler dann:> error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""char *> __cdecl bar(void)" (?bar@@YAPADXZ)" in Funktion "_main".
Du hast als C++ kompiliert. Da sind die Regeln anders.
Adam P. schrieb:> Kann man etwa im VS2013 als C kompilieren?
Natürlich, wenn die Sourcefiles *.c heißen, wird der native C-Compiler
verwendet. Der ist etwas angestaubt (d.h. kennt kein C99 oder neuer),
aber funktioniert davon abgesehen vorzüglich.
donvido schrieb:> Das Einbinden im Delphicode (dort werden auch Parameter übergeben)> funktioniert aber einwandfrei.
64-Bit oder 32-Bit?
In 32-Bit können verschiedene Aufruf-Konventionen zu lästigen Stack
Überläufen führen. Das merkt man aber oft nur bei sehr vielen Aufrufen
und kleinem Stack.
In 64-Bit ist das Aufräumen des Stacks einheitlich gelöst, calling
conventions sind hier IIRC no-ops.
Nochwas: Es gibt mehrere Möglichkeiten wie ein Symbol einer DLL
exportiert und in Delphi importiert wird. Einige davon ignorieren
Unterschiede bei Calling Conventions.
Adam P. schrieb:> Kann man etwa im VS2013 als C kompilieren?
Ja, über die Dateiendung (siehe Rufus) oder per Flag /Tc.
Der Schwerpunkt liegt auch bei neueren Versionen des MS-Compilers klar
auf C++.
"The Visual C++ C compiler is generally compatible with the ISO C99
standard, but not strictly compliant. In most cases, portable C code
will compile and run as expected. Visual C++ does not support most of
the changes in ISO C11."
Man kann inzwischen aber wohl auch Clang (Windows, Android, iOS) und GCC
(Android, Linux - Remote oder über das Linux-Subsystem) in VS verwenden.
Dr. Sommer schrieb:> Was ist denn deiner Meinung nach falsch? Wenn du bar() schreibst,> bedeutet das "beliebige Parameter beliebigen Typs". Das ist kompatibel> zu den angegebenen Parametern.
Nicht ganz. Ein Funktionsprototyp ist inkompatibel zu einer K&R-
Deklaration, wenn er Argumenttypen enthält, die einer Promotion
unterworfen sind. Dazu zählt auch bool, wenn es über stdbool.h als _Bool
definiert ist. Der Compiler müsste deswegen einen Fehler ausgeben.
Gibt er keinen Fehler aus, kann es daran liegen, dass
- bool nicht mittels stdbool.h als _Bool, sondern durch den Benutzer als
int oder unsigned int definiert ist,
- das MS-spezifische __dllspec(dllexport) die beiden Deklarationen
kompatibel macht (mit diesen MS-Erweiterungen kenn ich mich nicht aus)
oder
- der Compiler einen Bug hat.
Bei folgendem Code