Per quanto strano possa sembrare, ho bisogno di chiamare una funzione in C++, per la quale non conosco la firma. Fondamentalmente, voglio consentire all'utente di specificare un elenco di argomenti e tipi di argomenti e quindi provare a chiamare una determinata funzione con questi argomenti. Vorrei quindi sapere se la chiamata alla funzione ha funzionato o meno, e se lo ha fatto (miracolosamente), qual è il valore di ritorno (a condizione che il tipo di reso non sia nullo). C'è un modo per riuscirci? Grazie.Chiamata di funzione C++ con i parametri sconosciuti al momento della compilazione
risposta
Non sembra strano, ma non è possibile farlo in C++. Le firme delle funzioni C++ vengono verificate in fase di compilazione. Il meglio che puoi fare è passare un vettore, o un contenitore simile, contenente i parametri della funzione per la funzione. Anche allora, i tipi (o almeno il tipo di base, se si utilizza l'ereditarietà) dovrebbero essere noti al momento della compilazione.
@Neil Butterworth: La tua conclusione potrebbe essere giusta, ma il tuo ragionamento è fallace. Lo stesso vale per C# (tipizzato staticamente), ma è possibile fare ciò che l'OP sta richiedendo usando la reflection. Sì, so che il C++ non ha capacità di riflessione. – jason
Ovviamente. Il C++ ti consente di fare qualsiasi cosa, ma a quale scopo? Sembra improbabile che l'OP voglia scrivere un meccanismo di riflessione generico per C++. –
@Neil Butterworth: sono d'accordo. E la domanda suggerisce un grande odore di design. – jason
Se si ha accesso al compilatore C++ durante l'esecuzione, è possibile scrivere la chiamata postulata in un file, compilarlo, quindi collegarlo dinamicamente come una DLL e provare a eseguirlo. Se i tipi di argomento sono errati o la funzione non esiste, il collegamento di runtime DLL non riesce; altrimenti la funzione viene chiamata e si ottiene il valore di ritorno.
Consenti alle tue funzioni di prendere un elenco di tipi di dati varianti, ad es. std::vector<boost::any>
e fare in modo che restituiscano un bool
che indica il successo o genera eccezioni in caso di errore.
Se si sta bene registrando le funzioni esposte in fase di compilazione, non è nemmeno necessario posizionare tale restrizione sulle proprie funzioni e si può invece generare codice di colla per le conversioni necessarie.
+1 boost :: variante potrebbe anche essere utilizzata –
E se la funzione deve restituire valori di tipi diversi, restituire una variante. O qualche altro tipo discriminato. Boost non è richiesto. Potresti consegnare facilmente qualcosa per le tue esigenze specifiche. –
Cioè, un 'unione'. Penso che la "variante" sia un'ottima idea, anche se ... parlo MOLTO relativamente. – Potatoswatter
Naturalmente è possibile farlo in fase di esecuzione. Gdb, per esempio, lo fa. Ma richiede molto lavoro e comprensione dell'ambiente di destinazione. Sospetto che ci possa essere un modo migliore per fare ciò che vuoi.
Tuttavia, Gdb non lo fa "in C++"."Comprensione dell'ambiente di destinazione" cambia radicalmente il problema. –
Bene, se si è flessibili sul meccanismo, è possibile fare questo genere di cose utilizzando la spedizione dinamica.
Quello che devi fare è creare una classe base astratta che ha un metodo "esegui" che restituisce un valore di ritorno. Quindi hai un motore che mantiene una lista di puntatori agli oggetti di questa classe di base (astratta), che i clienti possono fornirti tramite una sorta di chiamata di registrazione.
I client scrivono le proprie implementazioni di "esegui" che possono fare tutto ciò che è necessario, a patto che riempiano correttamente il valore di ritorno del motore quando hanno finito. I loro "parametri personalizzati" sono implementati come membri extra della loro versione della classe, che possono essere compilati quando costruiscono l'oggetto, o da una chiamata separata.
Questo ti dà ciò di cui hai bisogno per chiamare la loro routine, eseguirla e controllare il risultato, senza dover sapere quali sono i loro parametri personalizzati o esattamente cosa fa la loro routine.
Questo suona come un sitter per includere un linguaggio di scripting digitato in modo dinamico nella tua app. Incorporare qualcosa come Lua o Python, rendere disponibili le funzioni che si desidera chiamare al linguaggio di scripting. Oppure, se stai cercando di implementare una cosa del genere, guarda Boost :: Python come un precedente su come farlo.
Questa è una domanda senza senso, dal momento che se l'utente (chi sta chiamando da c-codice) non conosce il tipo di argomento a tempo di compilazione, sarà non essere in grado di fornire gli argomenti della corretto tipo, anche se fosse possibile costruire un puntatore a funzione digitata in modo dinamico.
Anche l'esempio gdb
espresso in un'altra risposta presuppone che l'utente disponga di variabili del tipo appropriato e noto al punto della chiamata.
Poiché ciò è vero, deduco che l'utente conosca i tipi corretti dell'argomento e questo diventa quindi una questione su come creare una funzione in fase di compilazione che richiede un insieme di argomenti di tipo noto.
Ciò si ottiene semplicemente: Se l'utente ha un int
e due float
s e spera di ottenere un int
in cambio, e vuole chiamare la funzione presunta swizzle
il cui tipo di conseguenza deve essere int (IIIF*)(int, int, float)
, poi semplicemente dichiarare un puntatore di questa digitare, utilizzare ldload
per ottenere la funzione swizzle
e richiamarla.
Ci sono, tuttavia, alcuni casi speciali di questo che potresti essere in grado di raggiungere, ad esempio, se tutti gli argomenti sono puntatori.
noti che noto al momento della compilazione include casi come modelli, i cui valori sono inferita al momento della compilazione di informazioni di tipo esplicito o implicito al punto e il modello tempo istanziazione.
Come utilizzare i riferimenti di rvalue in C++ ox?
template<typename Function>
void FunCall(Function&& f)
{
f();
}
void Fun_Int(int x)
{
using std::cout;
using std::endl;
cout << "I''m Fun_Int with " << x << endl;
}
void Fun_Str(const string& str1)
{
using std::cout;
using std::endl;
cout << "I'm Fun_Str with " << str1 << endl;
}
void RvaluesDemo()
{
for (int i = 0; i < 5; i++)
{
FunCall([&]
{
Fun_Int(i);
});
}
string str = "ABCDEF";
for (int i = 0; i < str.size(); i++)
{
ostringstream os;
os << str[i];
FunCall([&]
{
Fun_Str(os.str());
});
}
}
- 1. ID tipo C++ al momento della compilazione
- 2. Rileva C# versione al momento della compilazione
- 3. Valutare una funzione al momento della compilazione con Template Haskell
- 4. Genera numeri univoci al momento della compilazione
- 5. stampa sizeof (T) al momento della compilazione
- 6. Come testare UIViewControllers al momento della compilazione?
- 7. Do C# lambdas esiste solo al momento della compilazione?
- 8. C++: disambigua questo codice al momento della compilazione?
- 9. Scala - Imposizione della dimensione del vettore al momento della compilazione
- 10. Mockito può verificare i parametri in base ai loro valori al momento della chiamata del metodo?
- 11. catch std :: allocazioni di funzioni al momento della compilazione
- 12. Determina la lunghezza della stringa netta al momento della compilazione
- 13. Disabilita la registrazione in Java al momento della compilazione
- 14. Piattaforma/processore di destinazione al momento della compilazione
- 15. Convalida il contenuto di std :: initializer_list al momento della compilazione
- 16. Rileva la presenza del modello al momento della compilazione
- 17. Incluso un #define in tutti i file di origine .c al momento della compilazione
- 18. Gli array possono essere indicizzati al momento della compilazione?
- 19. display intero al momento della compilazione a static_assert()
- 20. Forza una stretta coercizione implicita al momento della compilazione
- 21. Come si generano staticamente dati float al momento della compilazione?
- 22. Leggere un file in una stringa al momento della compilazione
- 23. come applicare tipo non generico al momento della compilazione
- 24. Valutazione dell'espressione di primo livello al momento della compilazione
- 25. Come scambiare due parametri di un modello variadico al momento della compilazione?
- 26. Qual è un valore noto al momento della compilazione?
- 27. Impossibile trovare un punto di ingresso al momento della chiamata C++ DLL in C#
- 28. E 'possibile modificare la "chiamata di funzione" al momento di pre-elaborazione o il tempo di compilazione
- 29. L'UB garantito può essere rifiutato al momento della compilazione?
- 30. Metodo di fabbrica - Parametri sconosciuti
Penso che una domanda importante sia * "Perché?" * C'è probabilmente un modo molto più semplice. – GManNickG
Chiamerai sempre la stessa funzione? Oppure l'argomento/elenco parametri seleziona la funzione che verrà chiamata? –
Sì, sembra che tu abbia qualcosa che vuoi veramente fare con questo piccolo esperimento mentale. Che cos'è? – Omnifarious