2009-08-07 16 views
33

Mam plik źródłowy C++ i plik źródłowy Python. Chciałbym, aby plik źródłowy C++ był w stanie wykorzystać zawartość źródłowego pliku Pythona jako duży napis literowy. Mógłbym zrobić coś takiego:C/C++, czy możesz # dołączyć plik do literału literowego?

char* python_code = " 
#include "script.py" 
" 

Ale to nie zadziała, ponieważ na końcu każdej linii muszą znajdować się \ 's. Mogłem ręcznie kopiować i wklejać zawartość kodu Pythona i otaczać każdą linię cudzysłowami i zakończeniem \ n, ale to jest brzydkie. Mimo że źródło Pythona zostanie skutecznie wkompilowane w moją aplikację C++, chciałbym zachować go w osobnym pliku, ponieważ jest on bardziej zorganizowany i działa lepiej z edytorami (emacs nie jest wystarczająco inteligentny, aby rozpoznać, że jest to C literał łańcuchowy jest kodem Pythona i przełącz się do trybu Pythona, gdy jesteś w nim).

Proszę nie sugerować używam PyRun_File, to co staram się unikać w pierwszym miejscu;)

+0

Wiem, że to jest duplikat. –

+3

Jeśli jest to duplikat, czy możesz podać link? Rozejrzałem się i nic nie widziałem przy moich wyszukiwanych terminach. –

+0

Czy poprzednia wersja python była specyficzna? Ponieważ jest to bardziej ogólne pytanie. –

Odpowiedz

35

C/C++ preprocesora działa w jednostkach żetonów oraz ciąg dosłowny jest single token. Jako takie nie można interweniować w środku literału ciągłego w ten sposób.

Można przetwórz script.py w coś podobnego:

"some code\n" 
"some more code that will be appended\n" 

i #include że jednak. Lub możesz użyć xxd​ -i do wygenerowania tablicy statycznej C gotowej do włączenia.

+11

+1 dla xxd. Skrypt prawdopodobnie nie musi być literałem łańcuchowym. –

+0

Jak jednak preprocessować skrypt.py? Nie widzę sposobu, aby to zrobić z CPP. Chyba że masz na myśli również zewnętrzne narzędzie, takie jak sed. –

+0

Zewnętrzne narzędzie, tak. Nie możesz robić tego, co chcesz, tylko dzięki CPP. – bdonlan

1

Będziesz musiał wykonać pewne własne przetwarzanie na kodzie Pythona, aby poradzić sobie z podwójnymi cudzysłowami, ukośnikami, trigrafami i innymi możliwymi rzeczami, które się w nim pojawiają. Możesz jednocześnie zamienić znaki nowego wiersza w \ n (lub ukośnik odwrotny) i dodać podwójne cudzysłowy na każdym końcu. Rezultatem będzie plik nagłówkowy wygenerowany z pliku źródłowego Python, który możesz wtedy #include. Użyj procesu budowania, aby zautomatyzować to, aby nadal można było edytować źródło Pythona jako Python.

1

Możesz użyć Cog jako części procesu kompilacji (aby wykonać wstępne przetwarzanie i osadzić kod). Przyznaję, że wynik tego prawdopodobnie nie jest idealny, ponieważ wtedy zobaczysz kod w obu miejscach. Ale zawsze, gdy widzę "Python", "C++" i "Preprocessor" w bliskości klosów, uważam, że zasługuje na wzmiankę.

-8

Użyj fopen, getline i fclose.

+2

To jest odpowiednik pliku PyRun. Pomysł polega na dołączeniu go do pliku wykonywalnego w czasie kompilacji, więc nie muszę robić tego rodzaju rzeczy. –

+1

Spowoduje to pobranie zawartości wykonawczej pliku znajdującego się na komputerze wykonawczym, a nie kompilacji zawartości pliku na komputerze kompilacji. –

4

Najlepszym sposobem na zrobienie czegoś takiego jest dołączenie pliku jako zasobu, jeśli twoje środowisko/zestaw narzędzi ma taką możliwość.

Jeśli nie (np. Systemy wbudowane itp.), Można użyć narzędzia bin2c (np. http://stud3.tuwien.ac.at/~e0025274/bin2c/bin2c.c). Zajmie to binarną reprezentację pliku i wypluje plik źródłowy C, który zawiera tablicę bajtów zainicjowanych dla tych danych. Konieczne może być pewne ulepszenie narzędzia lub pliku wyjściowego, jeśli chcesz, aby tablica została "\ 0" zakończona.

Incorporate uruchamiając narzędzie bin2c w swoim makefile (lub jako etap pre-build niezależnie od używasz do kierowania buduje). Następnie wystarczy skompilować plik i połączyć go z aplikacją, a twój ciąg (lub jakikolwiek inny obraz tego pliku) siedzi w kawałku pamięci reprezentowanej przez tablicę.

Jeśli dodajesz plik tekstowy jako ciąg znaków, powinieneś wiedzieć, że zakończenia linii mogą nie odpowiadać oczekiwanym funkcjom - może to być kolejna rzecz, którą chcesz dodać do narzędzia bin2c lub będziesz chciał upewnić się, że twój kod poprawnie obsługuje wszystkie zakończenia linii w pliku. Być może zmodyfikuj program bin2c tak, aby miał przełącznik "-s", który wskazuje, że chcesz, aby plik tekstowy był dołączony jako ciąg, więc zakończenia linii będą znormalizowane, a zero bajtów będzie na końcu tablicy.

9

To nie doprowadzi cię do końca, ale będzie ci bardzo cholernie blisko.

Zakładając script.py zawiera to:

print "The current CPU time in seconds is: ", time.clock() 

pierwsze, zawiń go tak:

STRINGIFY(print "The current CPU time in seconds is: ", time.clock()) 

Potem, tuż przed to go to zrobić:

#define STRINGIFY(x) #x 

const char * script_py = 
#include "script.py" 
; 

Jest prawdopodobnie jeszcze bardziej ciasną odpowiedź, ale wciąż szukam.

+0

Pan, proszę, zrób ciasteczko! 2 lata tańca wokół numeru –

+1

Miałem (na pewno rzadki) przypadek, w którym czasami potrzebowałem dołączyć ten sam plik co kod, a czasem jako ciąg (nie pytaj;)). Dodałem więc w dołączonym pliku '#ifndef STRINGIFY \ n #define STRINGIFY (x) x \ n # endif', a kiedy chcę go dołączyć jako kod, upewniam się, że STRINGIFY nie jest zdefiniowany. Cudownie działa także w przypadku plików wieloliniowych! –

-2

Oto jak zautomatyzować konwersję z cmd.exe

------ html2h.bat ------

@echo off 
echo const char * html_page = "\ 
sed "/.*/ s/$/ \\n\\/" ../src/page.html | sed s/\"/\\\x22/g 
echo. 
echo "; 

Nazwano jak

cmd /c "..\Debug\html2h.bat" > "..\debug\src\html.h" 

i dołączony do kodu przez:

#include "../Debug/src/html.h" 
printf("%s\n", html_page); 

Jest to podejście dość zależne od systemu, ale jak większość ludzi, nie podobał mi się zrzut heksadecymalny.

Powiązane problemy