ho a che fare con un sistema di C che offre un gancio di questa forma:Proxying uno std :: funzione a una funzione C che vuole una matrice di argomenti
int (*EXTENSIONFUNCTION)(NATIVEVALUE args[]);
E 'possibile registrare un EXTENSIONFUNCTION e la numero di argomenti necessari.
La mia idea era che avrei creato una classe Extension
per concludere un'estensione. Sarebbe in grado di essere costruito da una funzione std :: (o qualsiasi Callable, idealmente, ma diciamo solo che contiene una funzione std :: per ora). E l'estensione accetta i parametri Value, che contengono NATIVEVALUE (ma sono maggiori). Mi occuperei automaticamente del conteggio dei parametri con sizeof...(Ts)
, ad esempio. Si potrebbe assomigliare a questo:
Extension<lib::Integer, lib::String> foo =
[](lib::Integer i, lib::String s) -> int {
std::cout << i;
std::cout << s;
return 0;
}
Il problema è che, al fine per la libreria C per registrare e chiamarlo, vuole che l'interfaccia basata su array. : -/
Ho cercato di convincere il compilatore a scrivere un piccolo shim, ma non vedo il modo di farlo. Posso avere un variadic operator()
su Extension, ed eseguire un loop di runtime sul NATIVEVALUE per ottenere un array di Value []. Ma cosa faccio con quello? Non riesco a chiamare la funzione std :: con esso.
Quindi sembra che sia necessario creare un'istanza EXTENSIONFUNCTION che chiama la mia std :: function, come membro di ogni istanza Extension.
Ma fondamentalmente mi trovo di fronte a un muro dove ho una classe di moduli variadici per l'estensione ... e quindi una sorta di "non posso arrivarci da qui" in termini di prendere questo NATIVEVALUE args[]
e poterlo fare chiama la funzione std :: con loro. Se std :: function fosse disposto a essere invocato con uno std :: array di argomenti, questo lo risolverebbe, ma ovviamente non è così che funziona.
È possibile creare uno spessore di questo tipo? La cosa "brutto" che posso fare è solo proxy per un altro array, come:
Extension<2> foo =
[](lib::Value args[]) -> int {
lib::Integer i (args[0]);
lib::String s (args[1]);
std::cout << i;
std::cout << s;
return 0;
}
Ma non è come ergonomico. Sembra impossibile, senza conoscere la convenzione di chiamata e fare una sorta di assembly inline per elaborare i parametri e CHIAMARE la funzione (e anche quella funzionerebbe solo per le funzioni, non Callables in generale). Ma la gente qui hanno dimostrato possibile l'impossibile prima, di solito per mezzo di "che non è quello che vuoi, quello che realmente vuole è ..."
UPDATE: Ho appena trovato questo, che sembra promettente ... sto ancora cercando di digerire la sua rilevanza:
"unpacking" a tuple to call a matching function pointer
(Nota: ci sono un paio di questioni trasversali in quello che mi propongo di fare un altro punto è di tipo inferenza da lambda.. La risposta qui sembra essere la migliore scommettere su che ... sembra funzionare, ma non so se si tratta di "kosher": Initialize class containing a std::function with a lambda)
Poiché 'EXTENSIONFUNCTION' non sembra richiedere un' void * userData' per poter chiamare la propria 'Extension', non vedo come risolvere il problema. – Jarod42
Che cos'è 'NATIVEVALUE'? Forse puoi passare un puntatore a 'Extension' nel primo elemento dell'array. –
Ho avuto un tempo un po 'difficile leggere quello che hai inserito qui, ma io * penso * forse è [qualcosa di simile] (http://ideone.com/fJlkK6). Altrimenti, spero che almeno ti dia qualche idea. Buona fortuna. – WhozCraig