Jak zmusić linkera by wypełnil char[] = { "tekstem z pliku" } ?

0

Jak w temacie.. http://stackoverflow.com/questions/410980/include-a-text-file-in-a-c-program-as-a-char

Przykładowo jeśli zdefiniuje w pliku nagłówkowym extern char x[]; chce aby podczas kompilacji zawartość tekstu została wczytana z pliku przypisanego do nazwy zmiennej x.

Nie znam sie kompletnie na działaniu windres.exe (rc/res) czy to właściwy kierunek poszukiwań?
Chodzi mi o mozliwie przenośne multiplatformowe - bez angażowania WinAPI i w miare uniwersalne dla kompilatorów.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa380599(v=vs.85).aspx
Czy wystarczy użyć #pragma do linkera a może wystarczy #define macro(VA_ARGS) + #include?

Być może odpowiedź jest w zasięgu ręki mam nadzieje że ktoś z was ułatwi zadanie. Słowo klucz: GLSL ale nie tylko... bo również asm("") albo Lua https://gist.github.com/randrews/939029; Asembler ogranicza możliwości do MOC lub preprocesorem gdyż wymaga wypełnienia tekstem już w procesie kompilacji - zatem opcjonalnie. Odpada opcja { "linia\r\n" "kolejna"} ponieważ zmusza do pisania "\n" na końcu każdej linijki. Głownie chodzi mi o gtShaderString() czyli właściwie również OpenCL clCreateProgramWithSource(). Zastanawiałem sie plikami .s ale asembler asemblerowi nie równy GAS, FASM, NASM, YASM itd.
http://www.linuxjournal.com/content/embedding-file-executable-aka-hello-world-version-5967#comment-348129
Czy C przewiduje jakiś uniwersalny sposób?

1
 
char x[] = {
#include <x>
};

Coś takiego nie da rady?

0

.

0
J0ras napisał(a):

O TAkie coś chodziło?

[bits 32]
section .text
    global string

string:
    db "dupa lol cyc", 0xa, "ahaha", 0xa, 0
 

}



Blisko, ale nie..
http://www.atari-forum.com/viewtopic.php?t=26393

[code]char *binclude(void)
{
    static char *buf_addr;

    __asm__ __volatile__(
        "       move.l      #label,%[addr]  \n\t"
        "       .data                       \n\t"
        "label:                             \n\t"
        "       .incbin     \"binary.bin\"  \n\t"
        "       .align      2               \n\t"
        "       .text                       \n\t"
        : [addr] "=g" (buf_addr)
        :
        :
    );

    return buf_addr;
}

int main(int argc, char *argv[])
{
    char *b;

    b = binclude();

    /* do something with b */
}
[/code]

W orginale jesst static problemik, funkcja nie jest thread safe bo Atari i pewnie stary preprocesor. Gdyby zrobić w sylu binclude(label, nazwapliku) asm("..." #label "..." #nazwapliku "...") chyba bedzie okej. Pokombinuje analogicznych metod dla każdego kompilatora z osobna.

EDIT:
No niestety opcja incbin odpada z kompilatorem Microsoftu.
Pozostaje zaprzyjaźnić sie z objcopy? formatem coff http://www.ti.com/lit/an/spraao8/spraao8.pdf lub .rc
Albo własnym skryptowym konwerterem http://tomeko.net/online_tools/cpp_text_escape.php?lang=en który zaktualizuje wydzielony plik .c z definicjami char x[] = { "" };
Makro dawało by możliwość np. linkowania plików statycznie lub dynamicznie - wywołując open() i read(); Zależnie od jednego #define. c_incbin byłby ideałem.
0

Najprościej i najskuteczniej napisać skrypt, który przekonwertuje zawartość pliku do kodu źródłowego definiującego tablicę.
Następnie należy w pliku projektu (np Makefile) dodać właściwe zależności.
Takie rozwiązanie stosowane jest przykładowo w Qt (tak są dodawane zasoby), które jest wielkoformatowe.

1
MarekR22 napisał(a):

Najprościej i najskuteczniej napisać skrypt, który przekonwertuje zawartość pliku do kodu źródłowego definiującego tablicę.
Następnie należy w pliku projektu (np Makefile) dodać właściwe zależności.
Takie rozwiązanie stosowane jest przykładowo w Qt (tak są dodawane zasoby), które jest wielkoformatowe.

Z konieczności poszedłem za Twoimi sugestiami, no chyba nie do końca tak jest jak opisujesz z Qt http://doc.qt.io/qt-5/resources.html ale generalnie sprowadza sie do systemu tworzenia przez prekompilator = skrypt i podrzuania linkerowi zasobów do exe. Po czym ładowania ich przy pomocy funkcji bibliotecznych. Na podobnej zasadzie działa Qt Translator. Inny system to przez dostarczanie ich np. spakowanych w archiwum (zip). Po czym na wywołaniu funkcjach bibliotecznych którymi te zasoby można odczytać. http://stackoverflow.com/questions/1656968/platform-independent-resource-management LZ4, miniLZO, zlib, PAK (Quake)
Linux resource manager http://www.taniwha.com/~paul/res/

Biblioteka imagemagic posiada pomocniczy skrypt dokładnie taki jak sugerujesz przy czym on wczytuje obrazy(również skompresowane) do mapy bitowej w formie array.
System skryptów jest zawarty w CMake: CPack. Nie tworzy narzutu.
Znalazłem 2 programy do konwersji plik binarny -> kod w C https://www.fourmilab.ch/xd/ oraz http://www.deadnode.org/sw/bin2h/
Powiedzmy że problem jest stary jak świat i jest wiele metod bo C samo w sobie nie przewiduje importu binarnego - a szkoda :)

0

Wydziergałem coś takiego:

 #define __incbin(variable, filename)								\
    __asm__ __volatile__(                                            \
        ".section .rodata"                                      "\n"\
        ".global _"#variable                                    "\n"\
        ".type _"#variable", @object"                           "\n"\
        ".align 32"                                             "\n"\
        "_"#variable": .incbin "#filename               		"\n"\
\
        ".global _"#variable"_size"                             "\n"\
        ".type _"#variable"_size, @object"                      "\n"\
        ".align 32"                                             "\n"\
        #variable"_size: .int "#variable"_size - _"#variable    "\n"\
\
        ".int 0"                                                "\n"\
        :                                                           \
        :                                                           \
        :                                                           \
        );

Test w minimalnej formie:

 extern char x[];
int main(int argc, char *argv[])
{
__incbin(x,"D:/prc++/x86_libraries/SSTSOFT/test.txt")
return 0;
}

MinGW4.9.2 kompiluje mi makro(plik.s) w takiej postaci:

 /APP
 # 238 "../../../x86_libraries/SSTSOFT/koperek32_main.cpp" 1
	.section .rodata
.global _x
.type _x, @object
.align 32
_x: .incbin "D:/prc++/x86_libraries/SSTSOFT/test.txt"
.global _x_size
.type _x_size, @object
.align 32
x_size: .int x_size - _x
.int 0

 # 0 "" 2
	.loc 3 241 0
/NO_APP

i sypie problemami w linijkach tuż za makrem:

 	movl	$0, %eax	 #, D.48405
	.loc 1 247 0
	leave
	.cfi_restore 5
	.cfi_def_cfa 4, 4
	ret
	.cfi_endproc
LFE1750:
  1. Error: CFI instruction used without previous .cfi_startproc
  2. Warning: .type pseudo-op used outside of .def/.endef ignored.
  3. Error: junk at end of line, first unrecognized character is `_'
    2 i 3 przyznaje że nie do końca kapuje .type bez _ (czyli samo x) sypie jedynie warningiem o .def
    Podejrzewam że chodzi o sekcje .data która namieszała mu i zapomniał o:
 _main:
LFB1750:
	.loc 1 225 0
	.cfi_startproc
	pushl	%ebp	 #
	.cfi_def_cfa_offset 8
	.cfi_offset 5, -8
	movl	%esp, %ebp	 #,
	.cfi_def_cfa_register 5
	andl	$-16, %esp	 #,
	call	_mcount
	.loc 1 225 0
	call	__monstartup	 #
	call	___main	 #
	.loc 1 226 0

Jak ten problem obejść? W którym miejscu umieścić wywołanie makra żeby zadziałało?
Wiem że najłatwiej byłoby to char x[] zdefiniować w osobnym .s bez udziału inline asembly, ale jeśli opcja z makrem zadziała mam nadzieje dopisać wersje dla MSVC która skorzysta z FindResource zaszytego w funkcji __incbin() a w przypadku kompilacji linuxowej jeszcze innej opcji ładowania - zależnie od użytego kompilatora.

W międzyczasie znalazłem inne gotowce w jednym jest niemal kropka w kropke to co testuje:
https://woboq.com/blog/data-and-initialisation.html
http://blog.kowalczyk.info/article/zy/Embedding-binary-resources-on-Windows.html
https://github.com/graphitemaster/incbin
http://dox.ipxe.org/embedded_8c_source.html
https://www.devever.net/~hl/incbin
https://stackoverflow.com/questions/4864866/c-c-with-gcc-statically-add-resource-files-to-executable-library
https://stackoverflow.com/questions/4158900/embedding-resources-in-executable-using-gcc
https://stackoverflow.com/questions/2933295/embed-text-file-in-a-resource-in-a-native-windows-application

A ten prosty przykład jak by nie kombinował - nie działa :/
@J0ras?

1

Czy C przewiduje jakiś uniwersalny sposób?

Tak.
0. Tekst umieścić w pliku .txt

  1. Napisać program który wczytuje plik tekstowy i wypluwa przerobiony na .h - odpowiednio przeformatowany.
  2. Dodać kompilację tego programu do makefile'a
  3. Dodać uruchomienie tego programu do makefile'a, z zachowaniem odpowiednich zależności.
    Nie ma sensu angażować do tego asemblera.

1 użytkowników online, w tym zalogowanych: 0, gości: 1