Est-il possible de compiler un code supplémentaire au moment de l'exécution en C ou C++?
Voici ce que je veux faire:
- L'exécution d'un programme et d'initialiser certaines structures de données.
- Ensuite compiler du code supplémentaire qui peut accéder/modifier les structures de données existantes.
- Répétez l'étape 2, si nécessaire.
Je veux être capable de le faire avec les deux C
et C++
à l'aide de gcc
(et éventuellement Java
) sur les systèmes de type Unix (en particulier Linux et Mac OS X). L'idée est essentiellement de mettre en œuvre un read-eval-print loop pour ces langues, qui compile les expressions et les déclarations qu'ils sont entrés et l'utilise pour modifier les structures de données existantes (quelque chose qui se fait tout le temps dans les langages de script). Je suis en train d'écrire cet outil dans python
, ce qui génère le C
/C++
fichiers, mais cela ne devrait pas être pertinentes.
J'ai exploré le faire avec les bibliothèques partagées mais qui a appris que la modification des bibliothèques partagées n'affecte pas les programmes qui sont déjà en cours d'exécution. J'ai aussi essayé d'utiliser la mémoire partagée, mais ne pouvait pas trouver un moyen de charger une fonction sur le tas. J'ai également étudié à l'aide de code assembleur, mais n'ont pas encore tenté de le faire.
Je préfère ne pas utiliser les compilateurs autres que gcc
à moins qu'il n'y a absolument aucun moyen de le faire dans gcc
.
Si quelqu'un a des idées ou sait comment faire cela, toute aide sera appréciée.
Vous devez vous connecter pour publier un commentaire.
Je pense que vous pouvez être en mesure d'accomplir cette tâche en utilisant les bibliothèques dynamiques de chargement et lors de l'exécution (à l'aide de
dlopen
et amis).Vous devraient à l'évidence être de la compilation du nouveau code comme vous allez le long, mais si vous gardez le remplacement de
mynewcode.so
je pense que cela fonctionnera pour vous.RTLD_NODELETE
drapeau). Prendre tout cela avec un grain de sel bien :).Il y a une solution simple:
À l'utilisation de vos structures, vous devez inclure le même en-tête des fichiers comme dans l'application hôte.
des structures.h:
main.cpp:
de sortie:
Vous pouvez également créer mutable programme qui va changer lui-même (le code source), la recompilation de vous-même et puis le remplacer réels de l'exécution avec
execv
et d'économiser les ressources avec de la mémoire partagée.Même si LLVM est maintenant, aujourd'hui utilisé principalement pour ses optimisations et backend rôles dans la compilation, comme son cœur, c'est le Bas Niveau de la Machine Virtuelle.
LLVM pouvez JIT code, même si le type de retour peut être tout à fait opaque, donc si vous êtes prêt à emballer votre propre code autour d'elle et ne vous inquiétez pas trop à propos de l'jette qui vont avoir lieu, il peut vous aider.
Cependant, C et C++ ne sont pas très sympa pour ce genre de chose.
Oui - vous pouvez le faire avec Runtime Compilé En C++ (ou de prendre un coup d'oeil à la RCC++ blog et les vidéos), ou de l'une de ses alternatives.
Cela peut être fait de façon portable avec OpenCL
OpenCL est un largement pris en charge standard, principalement utilisé pour le déchargement des calculs de matériels spécialisés, tels que les Gpu. Cependant, il fonctionne très bien sur Cpu et effectue au moment de l'exécution de la compilation de C99-comme le code comme l'une de ses caractéristiques principales (c'est la façon dont le matériel portabilité est atteint). Les versions plus récentes (2.1+) acceptent également d'un grand sous-ensemble de C++14.
Un exemple de base d'un tel moment de l'exécution de la compilation & l'exécution pourrait ressembler à quelque chose comme ceci:
Si rien d'autre ne fonctionne - en particulier, si le chargement d'une bibliothèque partagée finit par ne pas être pris en charge sur votre plate-forme d'exécution, vous pouvez le faire à la dure.
1) utiliser system() ou n'importe quoi d'exécuter gcc ou faire ou que ce soit pour générer le code
2) lier comme un plat binaire ou d'analyser quel que soit le format (elfe?) l'éditeur de liens sorties sur votre plate-forme vous-même
3) trouvez-vous exécutable pages, soit par mmap () ing un fichier exécutable ou faire faire un mmap anonyme avec le bit d'exécution de définir et de copier/déballage de votre code (pas toutes les plates-formes de soins à ce sujet, mais nous supposons que vous avez un qui n')
4) vider les données et les instructions de caches (depuis la cohérence entre les deux est généralement pas garanti)
5) appeler par l'intermédiaire d'un pointeur de fonction, ou de quoi que
Bien sûr, il y a une autre option, selon le niveau d'interaction que vous avez besoin, vous pourriez construire un programme séparé et soit de le lancer et d'attendre le résultat, ou bifurquer et lancez-le et parlez-lui par des tuyaux ou des sockets. Si cela peut répondre à vos besoins, il serait beaucoup moins difficile.