2016-07-20 37 views
-1

ich Makros wie Funktionen erklären verwenden:Wie die Art der unsecable „int toto“ für den Einsatz in Präprozessor bekommen

NATIVE(int, myfunctionname, int param1, int param2) 
NATIVE(int, myfunctionname, int param1, int) 

Die ‚NATIVE‘ Makro ist für einen Wrapper wie zu erzeugen:

int myfunctionname(int arg0, int arg1) { 
    return mystruct.myfunctionname(arg0, arg1); 
} 

Aus bestimmten Gründen kann ich LD_PRELOAD oder den Befehl ld --wrap nicht verwenden.

Das Hauptproblem, das ich jetzt habe, ist in der Lage, zum Kompilierungszeitpunkt den Typ "int" abrufen, wenn das Präprozessor-Token "int" ist oder wenn es "int param0" ist.

EDIT: Ich möchte in der Lage sein, beide zu verwenden:

NATIVE(int, myfunctionname, int param1, int param2) 
NATIVE(int, myfunctionname, int, int) 

aber nur die letztere funktioniert. Wie in den Kommentaren gefragt ist hier mehr Kontext:

#define c99_count(...) _c99_count1 (, ## __VA_ARGS__) /* If only ## worked.*/ 
#define _c99_count1(...) _c99_count2 (__VA_ARGS__,10,9,8,7,6,5,4,3,2,1,0) 
#define _c99_count2(_,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,n,...) n 

#define FULL_ARGS_0() 
#define FULL_ARGS_1(X0) X0 a0 
#define FULL_ARGS_2(X0,X1) X0 a0, X1 a1 
#define FULL_ARGS_3(X0,X1,X2) X0 a0, X1 a1, X2 a2 
#define FULL_ARGS_4(X0,X1,X2,X3) X0 a0, X1 a1, X2 a2, X3 a3 
#define FULL_ARGS_5(X0,X1,X2,X3,X4) X0 a0, X1 a1, X2 a2, X3 a3, X4 a4 

#define _ARGS_0() 
#define _ARGS_1(X0) a0 
#define _ARGS_2(X0,X1) a0, a1 
#define _ARGS_3(X0,X1,X2) a0, a1, a2 
#define _ARGS_4(X0,X1,X2,X3) a0, a1, a2, a3 
#define _ARGS_5(X0,X1,X2,X3,X4) a0, a1, a2, a3, a4 

#define CAT(a, ...) PRIMITIVE_CAT (a, __VA_ARGS__) 
#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__ 

/* 
gives a name X0 a0 
*/ 
#define FULL_ARGS(...) CAT (FULL_ARGS_, c99_count (__VA_ARGS__)) (__VA_ARGS__) 
#define ARGS(...) CAT (_ARGS_,c99_count (__VA_ARGS__)) (__VA_ARGS__) 

#define NATIVE(rtype, name,...)         \ 
    rtype name (FULL_ARGS(__VA_ARGS__)) \ 
    {                \ 
    return (*g_libc.name ## _fn) (ARGS (__VA_ARGS__));    \ 
    } 
+0

Nun, für einfache Typen wie Sie zeigen, werfen Sie einfach die "param * n *" von den Argumenten. Das Problem ist mit Typen wie 'int (param1 &) [4]', wo der Parameter * innerhalb * des Typs gehen muss. –

+0

Ich weiß, dass ich das lösen kann, indem ich "param n" entferne, aber ich suchte nach einer robusteren Option. Meine Frage ist: "Ist es möglich, wegzukommen, ohne 'param n' 'über Template-Maschinen oder declltype usw. fallen zu lassen? Ansonsten bedeutet das, dass ich hunderte von Zeilen in einem Upstream-Projekt ändern muss, was kein Spaß oder Spaß ist Änderung, um für das Projekt zu übernehmen. – mattator

+1

Ich bin mir nicht sicher, wie das Abrufen von 'int' hier hilft. Meinst du nicht "param1", "param2" usw.? – Quentin

Antwort

2
namespace detail_paramType { 
    template <class> 
    struct unpackType; 

    template <class T> 
    struct unpackType<void(T)> { using type = T; }; 
} 

#define PARAM_TYPE(...) \ 
    typename detail_paramType::unpackType<void(__VA_ARGS__)>::type 

Das ist ein bisschen schwierig war. Syntax wie using type = void (*param)(); kompilieren nicht, da der Typ keinen Namen enthalten soll.

Die Variablendeklaration Syntax ist kompatibel, aber bringt uns nicht näher an das Ziel, da wir nicht wissen, den Namen des Parameters:

void (*param)(); // Fine 
using type = decltype(???); // Now what ? We can't name param... 

jedoch Namen sind erlaubt (und ignoriert) innerhalb der Syntax die Parameter eines Funktionstyps. So stopft PARAM_TYPE seinen Parameter innerhalb eines Funktionstyps und übergibt ihn an unpackType, der den Typ des Parameters zurück leitet. Sie müssen den ursprünglichen Namen des Parameters nicht kennen, und er funktioniert für jeden Typ.

Live on Coliru

+0

Danke für die Hilfe, das ist in der Tat schlau. Es hat Probleme, wenn der Prototyp variadic Argumente ("...") enthält, aber ich denke, dass kann nicht geholfen werden, also nehme ich die Antwort an :) Danke wieder – mattator

+0

@mattator konnten Sie (haha) auf diesem Problem erweitern? – Quentin

+0

Zum Beispiel habe ich NATIVE (int, open64, const char * Pfad, int Flags, ...); Das gibt: ../model/libc.cc:59:63: Fehler: 'Typ' in 'Struktur detail_paramType :: unpackType ' keinen Typ Typname detail_paramType :: unpackType :: type – mattator