J'aimerais idéalement pouvoir ajouter (très répétitif) C / C ++ code à mon code actuel, mais à la compilation, code qui viendrait de dire que le stdout d'un script python, de la même manière que l'on le fait avec Macros.
Par exemple, disons que je veux avoir des fonctions qui dépendent des attributs publics d'une classe donnée, de pouvoir simplement écrire ce qui suit dans mon code C ++ serait une bénédiction: p> est-ce réalisable en utilisant des moyens conventionnels? Ou dois-je pirater avec des maquillages et des fichiers source temporaires? P> merci. P> p>
7 Réponses :
Un maquillage (ou équivalent) est un moyen "conventionnel"! p>
Vous pouvez essayer la bibliothèque de préprocesseur Boost. C'est juste une extension du préprocesseur ordinaire, mais si vous êtes créatif, vous pouvez atteindre presque tout ce qui y est. P>
Vous avez le plus probablement besoin de modifier un peu le maquillage. Il serait facile d'écrire un script (python) qui lit chacun de vos fichiers source sous forme d'étape de prétraitement supplémentaire, remplaçant les instances de DAMN, maintenant je veux faire quelque chose comme ça. < / p> EDIT: strong> Une règle comme celle-ci, coincée dans un matrice, pourrait être utilisée pour gérer l'étape de construction supplémentaire. Ceci n'est pas testé et ajouté uniquement pour certains tir à la complétude. P> générate_boring_functions code> (ou tout autre script-macro) avec le code correct, potentiellement juste En appelant
generate_boring_functions.py code> avec les bons arguments et contourner le besoin de fichiers temporaires en envoyant la source au compilateur sur une entrée standard.
Comment j'enverrais la source au compilateur via STDIN (sans l'utilisation de fichiers temporaires)?
En effet, mais je peux avoir Python analyser tous les fichiers, puis concaténer tout le code nécessaire dans le bon ordre (les en-têtes d'abord, etc.) facilement, appelez simplement quelque chose comme "Python Generate_All_Code.py | GCC -X CPP -O OUT - ", comme si j'étais compilé un gros fichier C ++ ... mauvaise idée?
@Manux, passe-temps directement à GCC, est susceptible de vous mettre dans un monde de blessure lorsque vous devez déboguer votre sortie Python. Je vous suggère de sauvegarder sur un fichier Temp, puis de chat le fichier temporaire à GCC.
Si un fabricant n'est pas suffisamment conventionnel pour vous, vous pouvez vous procurer avec des macros intelligemment écrites.
class FooBarClass { DEFINE_BORING_METHODS( FooBarClass ) /* interesting functions begin here */ }
Je n'ai jamais utilisé cette technologie particulière, mais il semble que vous recherchiez quelque chose comme NED Batchelder's Cog Outil. P>
Les scripts Python sont incorporés dans un fichier source C ++ telle que lors de la fonction via le code C ++ supplémentaire, le code C ++ est généré pour le compilateur C ++ à consommer. Donc, votre processus de construction consisterait d'une étape supplémentaire pour que Cog produirait le fichier source C ++ avant que le compilateur C ++ soit invoqué. P>
J'ai rencontré exactement le même problème plusieurs fois.
Je l'utilise exactement dans la manière dont vous décrivez - (c.-à-d. Filename.cpp, "FileName.CPP") pour un ensemble de fichiers) . P>
Il est utilisé pour générer du code qui "enregistre" le code contenu dans un ensemble spécifique de fichiers sur une STD :: Plan, pour gérer les fonctions écrites de l'utilisateur à la bibliothèque sans recompiler de manière dynamique la bibliothèque entière. ou s'appuyant sur l'utilisateur (probablement novice programmeur) d'écrire un code C ++ correct syntaxiquement, par exemple les fonctions de classe d'implémenter. P>
Je l'ai résolu de deux manières (qui sont essentiellement équivalentes) p>
1 ) Une méthode purement c ++ "BootsTrapping", dans laquelle lors de la compilation, make compile un programme simple C ++ qui génère les fichiers nécessaires, puis appelle un deuxième maquillage qui compilait le code réel généré dans les fichiers temporaires. P>
2) une méthode à base de coquille qui utilise Bash pour accomplir la même chose (c'est-à-dire utilisez des commandes de shell simples à itération via les fichiers et de produire de nouveaux fichiers à Emplacement temporaire, puis appelez la sortie sur la sortie). p>
Les fonctions peuvent être émises sur un fichier chacune ou peuvent être émises sur un fichier monolithique pour la deuxième compilation. P>
Ensuite, les fonctions peuvent être chargées de manière dynamique (c'est-à-dire Ils sont compilés comme une bibliothèque partagée), ou je peux recompiler tout le reste du code avec les fonctions générées incluses. p>
La seule partie dure était (a) de déterminer un moyen d'enregistrer les noms de fonctions uniquement (par exemple, en utilisant le préprocesseur J'ai inclus les parties dures du maquillage pour la postérité: p> Le premier maquillage appelé est le suivant: P> __ compteur __ code> ne fonctionne que s'il s'agit d'un fichier monolithique unique), et (b) de savoir comment appeler de manière fiable la fonction de génération dans le fabricant de fabrication avant le maquillage principal. P> L'avantage de la méthode pure-C ++ (par rapport à la bash) est qu'il pourrait éventuellement fonctionner sur des systèmes qui ne disposent pas du même shell de Bash Linux par défaut (par exemple, Windows ou MacOS), auquel cas bien sûr un cmake plus complexe La méthode est nécessaire. P>
BUILD_DIR="build/COMPILED_FILTERS";
rm -r $BUILD_DIR
mkdir -p $BUILD_DIR
ARGSET="( localmapdict& inputmaps, localmapdict& outputmaps, void*& userdata, scratchmats& scratch, const std::map<std::string,std::string>& params, const uint64_t& curr_time , const std::string& nickname, const std::string& desc )"
compfname=$BUILD_DIR"/COMPILED_FILTERS.cpp"
echo "//// START OF GENERATED FILE (this file will be overwritten!) ////" > $compfname #REV: first overwrites
echo "#include <salmap_rv/include/salmap_rv_filter_includes.hpp>" >> $compfname
echo "using namespace salmap_rv;" >> $compfname
flist=$(find $1 -maxdepth 1 -type f) #REV: add constraint to only find .cpp files?
for f in $flist;
do
compfnamebase=$(basename $f) #REV: includes .cpp
alg=${compfnamebase%.cpp}
echo $f " >> " $compfname
echo "void ""$alg""$ARGSET""{" >> $compfname
echo "DEBUGPRINTF(stdout, \"Inside algo funct "$alg"\");" >> $compfname; #REV: debug...
cat $f >> $compfname
echo "}""REGISTER_SAL_FILT_FUNC(""$alg"")" >> $compfname
done
echo "//// END OF GENERATED FILE ////" >> $compfname
Je pensais que les fabricants étaient des moyens conventionnels. Qu'avais tu en tête?
Quelles sont les fonctions ennuyeuses? Sont-ils quelque chose qui pourrait être résolu avec une solution basée sur des modèles?
Non, ce n'est pas contemporble, et je sais que les maquillages sont des moyens conventionnels, mais je veux dire quelque chose qui fonctionnerait juste en faisant le stupide "g ++ foo.cpp -o foo", je suppose que c'est trop à poser;)
Cette question semble intéressante, mais c'est un peu pas clair ce que vous voulez. Un exemple plus détaillé d'entrée / de sortie aiderait.
Je suis peut-être un peu en retard pour ajouter à ce sujet, mais vous pourriez trouver la question suivante pertinente: Stackoverflow.com/questions/39273219/...