Funktion "erstellen"
-
Hallo.
Ich weiss leider nicht wie man es nennen soll und so suche ich nun schon seit Stunden in google nach einer passenden Beschreibung/Hilfe.
ExprFunc1V = function(const x: Extended): Extended; SinC : ExprFunc1V; SinC := CompileExpr(ParseExpr('sin(x)/x',['x']),tyPass1V); // parse and compile expression Result := SinC(1.0); // evaluate the Expression FreeFunc(@SinC); // Free Function ShowMessage('Result = '+FloatToStr(Result));Ich möchte diesen Delphi Code gerne in C++ übernehmen, jedoch weiss ich nicht wie man so wie dort eine Funktion "erstellt".
Der erste Schritt wäre
typedef Extended __fastcall (*ExprFunc1V)(const Extended x);und
ExprFunc1V SinC;Aber wie caste(?) ich jetzt die Ausgabe von CompileExpr() in eine Funktion
ExprFunc1V SinC = (ExprFunc1V*)CompileExpr(ParseExpr("sin(x)/x", v, ARRAYSIZE(v)-1),tyPass1V); // Das bringts leider nicht :rolling_eyes:und gebe diese auch wieder frei?
Bitte einer muss das doch wissen, wenigstens nach welchem Begriff man suchen muss um irgendwie ansatzen zu können

-
Is das ein Funktionszeiger?
-
Ach oben die Zeile war nicht richtig
ExprFunc1V SinC = (ExprFunc1V)CompileExpr(ParseExpr("sin(x)/x", v, ARRAYSIZE(v)-1),tyPass1V); // ohne den SternDer Fehler daran ist aber das beim Start ein Speicherfehler Error kommt.
CompileExpr() ist **void ***
extern PACKAGE void * __fastcall CompileExpr(const Expression &Bytecode, tyPassType PT);Ich habe auch schon probiert
ExprFunc1V SinC = 0; SinC = (ExprFunc1V)CompileExpr(ParseExpr("sin(x)/x", v, ARRAYSIZE(v)-1),tyPass1V); // ohne den SternOft hilft es ja 0 zu setzen, leider hier nicht

Es compiliert, aber Speichererror bei Ausführung. Eine Ahnung woran es hängt?
-
midori schrieb:
Oft hilft es ja 0 zu setzen
Kann schon sein, aber nicht in C++.
Gibt denn CompileExpr() eine gültige Adresse zurück?
Und ob die Funktionssignatur von ExprFunc1V richtig ist, ist auch noch so ein Thema. Normalerweise nutzt man in C++ keine const by-value Übergaben.
-
Nunja, in C(++) kann man nicht wirklich neue Funktionen zur Laufzeit definieren - du könntest höchstens den Zeiger auf eine bereits existierend Funktion zurückliefern. Aber da du beliebige Nutzereingaben in Funktionen verwandeln willst, dürfte das etwas problematisch werden (da du für jede potentiell mögliche Eingabe die passende Funktion brauchst), da wäre vermutlich eine Parser-Klasse sinnvoller, die den String zur Laufzeit durchgeht:
class function_parser { public: function_parser(const std::string& the_func): m_func(the_func) {} operator()(double x, double y=0, double z=0) { // hier drin m_func auswerten und die Parameter einsetzen } private: std::string m_func; }(in dem Beispiel kann die berechnete Funktion bis zu drei Parameter haben)
Zum Parsen der Eingabe empfehle ich z.B. Spirit (hab' recht gute Erfahrung damit gemacht) oder lexx.
-
@_midori_
Wenn der Speicherfehler in der gezeigten Zeile kommt, dann ist es entweder die Funktion ParseExpr oder CompileExpr. Die Zuweisung des Ergebnis der Funktion CompileExpr (selbst wenn es eine ungültige Zahl ist) sollte erstmal keinen Fehler produzieren. Insofern ist es auch irrelevant, ob Du vorher die Variable auf 0 setzt. Wenn die zurückgebene Adresse ungültig ist (also kein Zeiger auf eine Funktion mit der gegebenen Signatur), bekommst Du einen Absturz, wenn Du versuchst, die Variable zu nutzen.@groovemaster
Extended ist in Delphi/C++Builder ein 10 Byte Floating Point Wert und damit "praktisch" ein POD. siehe z.B
http://www.merlyn.demon.co.uk/pas-type.htm
Daher ist das f(const Extended x) vergleichbar mit f(const double d).
-
@CStoll
Das Ding erzeugt tatsächlich eine neue Funktion. Siehe den Thread unter:
http://www.delphi-forum.de/viewtopic.php?t=36946&postdays=0&postorder=asc&start=20
Der geparste Ausdruck wird zur Laufzeit compiliert...
-
niemand schrieb:
Extended ist in Delphi/C++Builder ein 10 Byte Floating Point Wert und damit "praktisch" ein POD.
Viel inbteressanter ist allerdings, WIE der Parameter übergeben wird. const macht eigentlich nur bei by-reference
Sinn. Deshalb hab ich mich gefragt, ob die by-value Deklaration unter C++ überhaupt richtig ist.
-
Delphi entscheidet selbst ob const Parameter als Referenz übergeben werden oder nicht.
Der Grund warum man Parameter als const und by-Value deklariert, ist zu dokumentieren, dass innerhalb der Funktion der Wert nicht geändert wird (für den Leser der Funktion, nicht für den Aufrufer). Bei hinreichend kurzen Funktionen wird das natürlich wieder überflüssig.