Funktion um zwei Strings zu addieren
-
Danke schon mal für die Antwort. Ich habe es jetztz erstmal so:
extern "C" EXPORT int addstr(char *str1, char *str2, char *buffer) { MessageBoxA(0, str1, "Test", 0); return strlen(str1); }
Leider bekomme ich so immer eine Zugriffsverletzung beim Aufruf der Funktion. Ich sollte eventuell dazu sagen, dass sie in einer DLL liegt, aber das sollte erstmal keine Rolle spielen.
-
die msgbox sieht eigentlich ok aus, muss irgendwie am aufruf liegen.
btw: aber lass dich mal besser nach 'winapi' verschieben....
-
Also entschuldige, aber
Luckie schrieb:
Weil ich nicht weiß, wie man in C mit Zeichenketten umgeht
in Verbindung mit
Luckie schrieb:
Ich sollte eventuell dazu sagen, dass sie in einer DLL liegt, aber das sollte erstmal keine Rolle spielen.
hört sich böse an
Greetz, Swordfish
-
Die MessageBox war ja ursprünglich nur zur Kontrolle drinne. Um die geht es mir ja eigentlich gar nicht. Ich will eiegntlichn ur eine Funktion, die mir zwei Zweichenketten aneinanderhängt und das Ergebnis in den Parameter Buffer schreibt.
Das mit der MessageBox hat sich erledigt, ich hatte vergessen in Delophi die Aufrufkonvention anzugeben. Jetzt sieht es so aus:
extern "C" EXPORT int addstr(char *str1, char *str2, char *buffer) { strcat(str1, str2); strcpy(buffer, str1); return strlen(buffer); }
Jetzt bekomme ich aber wieder eine AccessViolation in der DLL. Mein korrespondierender Delphi Code sieht so aus:
type TAdd = function(a, b: Integer): Integer; stdcall; TAddStr = function(str1, str2: PChar; var Buffer: PChar): Integer; stdcall; procedure TForm1.Button1Click(Sender: TObject); var hLib: THandle; s: String; Add: TAdd; AddStr: TAddStr; res: Integer; str1, str2: String; Buffer: PChar; begin s := IncludeTrailingBackSlash(ExtractFilePath(ParamStr(0)))+ 'FirstDLL.dll'; hLib := LoadLibrary(PChar(s)); if hLib <> 0 then begin @Add := GetProcAddress(hLib, 'add'); if Assigned(Add) then begin res := Add(40, 2); ShowMessage(IntToStr(res)); end else ShowMessage(SysErrorMessage(GetLastError)); @AddStr := GetProcAddress(hLib, 'addstr'); if Assigned(AddStr) then begin str1 := 'Hello '; str2 := 'World'; GetMem(Buffer, length(str1) + length(str2)); try res := AddStr(PChar(str1), PChar(str2), Buffer); ShowMessage(string(Buffer)); finally FreeMem(Buffer); end; end else ShowMessage(SysErrorMessage(GetLastError)); FreeLibrary(hLib); end else ShowMessage(SysErrorMessage(GetLastError)); end;
-
Luckie schrieb:
extern "C" EXPORT int addstr(char *str1, char *str2, char *buffer) { strcat(str1, str2); strcpy(buffer, str1); return strlen(buffer); }
Jetzt bekomme ich aber wieder eine AccessViolation in der DLL.
da ist wohl ein speicherbereich zu klein.
mach besser sowas:int addstr (char *str1, char *str2, char *buffer) { return sprintf (buffer, "%s%s", str1, str2); }
btw: wieso ärgerste dich mit c rum wenn du delphi hast
-
Hier http://www.delphipraxis.net/post595290.html#595290 ist die Lösung.
Gute Frage. Cheffe will die DLL unbedingt in C haben (und mit GCC und Ecliipse, aber da sist eine andere Geschichte). Und da übe ich schon mal etwas und gucke mir das an. Da ich in Delphi aber etzwas fitter bin, habe ich die Testanwendung eben in Delphi schnell geschrieben.
-
Luckie schrieb:
Hier http://www.delphipraxis.net/post595290.html#595290 ist die Lösung.
jo, ist das selbe nur dass du's mit 3 funktionsaufrufen machst
-
Jupp. Aber es ging mir nur ums Prinzip.
-
Luckie schrieb:
extern "C" EXPORT int addstr(char *str1, char *str2, char *buffer) { strcat(str1, str2); strcpy(buffer, str1); return strlen(buffer); }
Jetzt bekomme ich aber wieder eine AccessViolation in der DLL.
Na bravo! Das ist mal wieder eins der typischen Beispiele dafür,
was passieren kann, wenn man unsauber programmiert.Ich gehe mal davon aus, daß die übergebenen Strings nicht
verändert werden sollen; genau das macht dieser Code aber!Er versucht str2 an den bestehenden str1 anzuhängen und danach
den jetzt veränderten str1 zu kopieren.Bei sauberer Nutzung des Modifiers const wär' das nicht passiert:
extern "C" EXPORT int addstr(const char *str1, const char *str2, char *buffer) { strcat(str1, str2); strcpy(buffer, str1); return strlen(buffer); }
Da hätte nämlich der Compiler bereits losgemeckert!
-
Wärest du meinem Link gefolgt, dann hättest du gesehen, dass ich es mittlerweile geändert habe und es jetzt läuft.
-
Luckie schrieb:
Wärest du meinem Link gefolgt, dann hättest du gesehen, dass ich es mittlerweile geändert habe und es jetzt läuft.
Eben nicht!
Ein Aufruf von z.B. addstr("Hello ", "world!", buffer);
dürfte bei deiner Signatur nicht möglich!Und gerade als als Moderator eines Programmierforums solltest du
doch mit gutem Beispiel vorangehen.
-
Und warum sollte das nicht möglich sein? Und was hat meine Funktion als Moderator damit zu tun?
-
hi luckie. javaner ist nun mal *javaner*, kennt "const correctness" von c++ und denkt, c haette das auch. hats aber nicht.
konkret denkt er, dass der compiler fehler spuckt, wenn eine funktion(const char*) mit einem einfachen char* aufgerufen wird (oder umgedreht). das gibt bei gcc gerade mal ne warnung, *wenn* man masochistische flags verlangt.nichtsdestotrotz verlangt C eine definitiv andere denkweise als delphi, insbesondere bei der stringbehandlung. ich moechte behaupten, beide welten zu kennen (ja, AnsiString ist ein record, welches einen fucked string enthaelt) und kann dir zumindest das verraten.
-
c.rackwitz schrieb:
hi luckie. javaner ist nun mal *javaner*, kennt "const correctness" von c++ und denkt, c haette das auch. hats aber nicht.
konkret denkt er, dass der compiler fehler spuckt, wenn eine funktion(const char*) mit einem einfachen char* aufgerufen wird (oder umgedreht).... das wäre aber auch legales C++ ... wenn du auf 'char *p = "foobar";' anspielst.
Da"duck&cover"niel
-
c.rackwitz schrieb:
nichtsdestotrotz verlangt C eine definitiv andere denkweise als delphi, insbesondere bei der stringbehandlung.
Und genau damit versuche ich mich gerade vertraut zu machen, weil ich das bei einem kommenden Projekt brauchen werden.
-
c strings sind nur eine null-terminierte kette von bytes im speicher
man kommt nur mittels zeiger aufs erste zeichen an sie ran
die laenge ist nicht teil des strings, sie muss ermittelt werden (durchscannen nach nullzeichen)
stringoperationen wie z.b. strcat sind wahnsinn: laufzeit O(n+m) fuer strcat, weil beide strings ganz gelesen werden muessen
eine kette von strcat()s sollte/muss handoptimiert werden (einen zielpointer mitschleppen, um das durchscannen zu reduzieren), sonst hast du einen shlemiel: http://www.joelonsoftware.com/articles/fog0000000319.htmles gibt stringliterale (literal eben, der kram zwischen den quotes) und die sind read-only. schreibversuch in ein literal resultiert demnach in einer zugriffsverletzung.
arrays kann man mit literalen initialisieren. dann kannst du ins array schreiben, aber das literal hat damit seine schuldigkeit getan.
ein array char foo[1000] = "hallo welt": ist 1000 bytes lang und die ersten so und so viel bytes enthalten die offensichtlichen zeichen, gefolgt von einem nullbyte (welches am ende von literalen uebrigens nichts zu suchen hat, wie manche es gerne machen). die laenge des *strings* ist vom nullbyte abhaengig. wenn du uber die arraygrenzen schreibst (was in c nicht mal bewarnt werden kann), hast du einen stack buffer overflow.
bei der uebergabe von arrays an eine funktion wird nur ein pointer uebergeben (ne zahl eben). in der funktion kannst du das richtige machen und den parameter als pointer ansehen, oder du kannst so tun als ob der parameter ein array waere und in der funktionsdefinition fuer diesen parameter dimensionen angeben:
void foo(char *str) {} void bar(char str[100]) {} // keiner garantiert, dass die funktion auch echt einen char[100] kriegt, aber wir tun mal so...
sizeof funktioniert so: sizeof(char[]) == laenge in bytes des verfuegbaren speichers; sizeof(char*) == wortgroesse in bytes. sizeof() ist also nutzlos, um die laenge eines strings zu bestimmen.
-
Die Tatsache, dass unter C Zeichenketten nur nullterminierende zeichen-arrays sind, war mir schon bekannt.
Und den Artikel von Joel kenne ich auch. Er schreibt sehr gut, wenn auch manchmal etwas langatmig.
-
@Luckie
Ich muß mich für meine gestrige Behauptung
entschuldigen; du hattest doch Recht!Die Compiler mit denen ich zuvor zu tun hatte (Solaris, Atari)
verlangten nach Einführung des const-Modifiers die
const-correctness.Dies war auch der Grund dafür,
daß wir bei Zusammenarbeit mit Siemens-Teams zu Anfang
immer Schwierigkeiten hatten. Diese lieferten uns C++-Header-Dateien
in denen (wegen Faulheit der Siemens-Programmierer) viele
Zeiger-Parameter nicht als const deklariert wurden, wobei
wir diese Funktionen mit const-Parametern aufrufen wollten.Das es heute auf einmal anders ist, ist mir entgangen
http://www.c-plusplus.net/forum/viewtopic-var-t-is-156434.html
Weiß jemand einen Link auf die heute gültigen Sprachspezifikationen?
-
Javaner schrieb:
Weiß jemand einen Link auf die heute gültigen Sprachspezifikationen?