Elektroda.pl
Elektroda.pl
X
CControls
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[ECLIPSE][GCC]Conditional include

yild 17 Lis 2015 12:41 804 10
  • #1 17 Lis 2015 12:41
    yild
    Poziom 14  

    Witam...

    Problem dotyczy gcc (arm eabi) w środowisku Eclipse:

    Składniowo używam C do projektu, z uwagi na brak OOP wymyśliłem sobie stworzenie pliku(ów) gdzie zdefiniowane będą funkcje zależna od hardware jednak mające identyczne nazwy funkcji, pliki te chcę włączać do projektu na poziomie preprocessora za pomocą 'ifdef':

    W Eclipse mam taką strukturę folderów/plików

    Code:

    inc
       lib
          mylib
             board
                type1.h
                type2.h
             config
                config.h
    src
       lib
          mylib
             board
                type1.c
                type2.c


    każdy z plików type1, type2 odpowiada za te samą czynność jednak różniącą się implementacją:

    plik type1.h
    Kod: c
    Zaloguj się, aby zobaczyć kod


    plik type2.h
    Kod: c
    Zaloguj się, aby zobaczyć kod


    plik type1.c
    Kod: c
    Zaloguj się, aby zobaczyć kod


    plik type2.c
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Do projektu dołączam poszczególne pliki nagłówkowe w pliku config.h

    plik config.h
    Kod: c
    Zaloguj się, aby zobaczyć kod


    oczywiście dostaję błędy typu multiple definitions of '...' przy funkcja1

    Widziałem rozwiązanie gdzie w plikach nagłówkowych był kod poszczególnych funkcji i takie coś było includowane w pliku 'c' - ale to nie jest ładne rozwiązanie.

    Jak rozwiązać taki kalambur, jak zrobić kompilację z identycznymi nazwami funkcji - wygląda to tak jakby gcc w Eclipse kompilował wszystko co jest w folderach inc/src.

    0 10
  • CControls
  • #2 17 Lis 2015 12:54
    tmf
    Moderator Mikrokontrolery Projektowanie

    Przede wszyskim skoro interfejs jest identyczny, to potrzebujesz tylko jednego pliku nagłówkowego. Jeśli kod jest w plikach c to jest problem, bo musiałbyś zrobić warunkową kompilację tych plików co jest możliwe tylko przez dyrektywy preprocesora, ale umieszczone w kodzie źródłowym, a nie w nagłówkach.
    Tak się zastyanawiam czy nie prościej byłoby prekompilować źródła i robić z tego bibliotekę, a później kod linkować tylko z odpowiednią wersją biblioteki? Albo jeszcze inaczej - każdej odmianie funkcji nadać inną nazwę, a w pliku nagłówkowym wiązać konkretną nazwę z nazwą widzianą i wykorzystywaną przez resztę kodu?

    0
  • CControls
  • #3 17 Lis 2015 12:56
    grko
    Poziom 33  

    Mozesz po prostu w w plikach *.c zrobic:

    #if defined(TYPE1)
    ...
    #endif

    0
  • #4 17 Lis 2015 13:53
    szelus
    Specjalista - Mikrokontrolery

    Tak, jak pisze tmf, albo biblioteki, albo owijki, tylko to trochę upierdliwe:

    plik type1.h

    Kod: c
    Zaloguj się, aby zobaczyć kod


    plik type2.h
    Kod: c
    Zaloguj się, aby zobaczyć kod


    plik type1.c
    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #5 18 Lis 2015 00:37
    yild
    Poziom 14  

    tmf: tak nagłówkowe są atm identyczne, zostawiłem tak bo mogę sobie odrębne komentarze dać w każdym z osobna (czy to będzie potrzebne nie wiem), co do bibliotek to się nie odważę na obecnym moim etapie nauki :).

    Grzegorz: jest to rozwiązanie chyba najprostsze z możliwych, aktualnie pliki type1.c type2.c mają po ok 100-150 wierszy (same definicje funkcji), problem następuje gdy chcę zdefiniować coś innego niż tylko funkcję, rozdział na pliki bardzo to systematyzował.
    Osobną sprawą jest późniejsze nagromadzenie podobnego kodu gdy dojdą type2.c... typen.c, jeszcze co gorsze jak ktoś obcy chciałby coś dodać swojego... ;)

    szelus/tmf: sprawdziłem sobie takie owijki na funkcje właściwe... kurcze gdyby tylko nie było pomieszania publiczne/prywatne funkcje w jednym pliku nagłówkowym, można by to uprościć dodatkowym poziomem kodu, poniżej całość:

    plik type1.h

    Kod: c
    Zaloguj się, aby zobaczyć kod


    plik type1.c
    Kod: c
    Zaloguj się, aby zobaczyć kod


    plik type2.h
    Kod: c
    Zaloguj się, aby zobaczyć kod


    plik type2.c
    Kod: c
    Zaloguj się, aby zobaczyć kod


    plik config.h
    Kod: c
    Zaloguj się, aby zobaczyć kod


    plik master.h
    Kod: c
    Zaloguj się, aby zobaczyć kod


    plik master.c
    Kod: c
    Zaloguj się, aby zobaczyć kod


    plik main.c (funkcja main)
    Kod: c
    Zaloguj się, aby zobaczyć kod


    i to się kompiluje bez błędów czy ostrzeżeń.




    yild napisał:

    Widziałem rozwiązanie gdzie w plikach nagłówkowych był kod poszczególnych funkcji i takie coś było includowane w pliku 'c' - ale to nie jest ładne rozwiązanie.


    To rozwiązanie też sobie sprawdziłem, jednak zamiast kodu w plikach .h wrzuciłem do .inc ...
    zawartość plików .c przeniesiona do .inc type1.c -> /inc/mylib/board/type1.inc, type2.c -> /inc/mylib/board/type2.inc

    Code:

    inc
       lib
          mylib
             config
                config.h
             board
                type1.h
                type1.inc
                type2.h
                type.inc
                types_common.h
    src
       lib
          mylib
             board
                types_common.h


    plik types_common.h (pusty...)
    Kod: c
    Zaloguj się, aby zobaczyć kod



    plik types_common.c
    Kod: c
    Zaloguj się, aby zobaczyć kod


    plik config.h
    Kod: c
    Zaloguj się, aby zobaczyć kod


    plik main.c
    Kod: c
    Zaloguj się, aby zobaczyć kod


    i to się kompiluje bez błędów czy ostrzeżeń.

    Pytanie które rozwiązanie lepsze/ładniejsze - może obydwa równie bzdurne ;)

    0
  • Pomocny post
    #6 18 Lis 2015 01:17
    grko
    Poziom 33  

    W czym rozwiazanie z zamiana *.c na *.inc oraz warunkowa kompilacja w pliku types.common.c jest lepsze od warunkowej kompilacji kazdego pliku types_xxx.c z osobna ?


    type1.c:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    type2.c:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Jak chcesz bardziej wyszukanego rozwiazania to polecam okreslic sobie jeden interfejs dla wszystkich modulow jako strukture ze wskaznikami do funkcji:

    iface.h:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    i w poszczegolnych plikach *.c cos takiego:

    iface_type1.c:
    Kod: c
    Zaloguj się, aby zobaczyć kod



    Takie rozwiazane umozliwia kompilacje wszystkich modulow bez warunkowych dyrektyw preprocesora. Wystarczy jedna kompilacja abyw wychwycic wszystkie bledy (w poprzednim rozwiazaniu trzeba przeprowadzic N warunkowych kompilacji).

    1
  • #7 18 Lis 2015 07:27
    yild
    Poziom 14  

    Widziałem rozwiązania z użyciem struct ale jak szukałem opisów do tego to znajdowałem tylko jakieś dziwnie pokręcone przykłady, które nie inspirowały nawet do wczytywania się co i jak, Twój sposób opisu użycia struct jest najczytelniejszy ze wszystkich :)

    Muszę się zastanowić, która metodę użyć.

    EDIT: dodano testy


    Code:

    inc
       libraries
          mylib
             config
                config.h
             board
                board_common.h
                board_iface.h
                board_type1.h
                board_type2.h
    src
       libraries
          mylib
             board
                board_common.c
                board_iface.c
                board_type1.c
                board_type2.c
       main.c         


    plik board_iface.h
    Kod: c
    Zaloguj się, aby zobaczyć kod


    plik board_type1.h
    Kod: c
    Zaloguj się, aby zobaczyć kod


    plik board_type1.c
    Kod: c
    Zaloguj się, aby zobaczyć kod


    plik board_type2.h
    Kod: c
    Zaloguj się, aby zobaczyć kod


    plik_board_type2.c
    Kod: c
    Zaloguj się, aby zobaczyć kod


    plik board_common.h (deklaracja wszystkich plików board_typex.h umożliwia sprawdzenie błędów kompilacji)
    Kod: c
    Zaloguj się, aby zobaczyć kod


    board_common.c
    Kod: c
    Zaloguj się, aby zobaczyć kod


    plik config.h
    Kod: c
    Zaloguj się, aby zobaczyć kod


    plik main.c
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Wszystko nawet działa, mam identyczny interfejs dostępu dla każdej z 'board', dodatkowo pozostały kod nie musi nic wiedzieć o iface_type1, iface_type2...iface_typen.
    Przy deklaracji w postaci:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    modyfikator const traci swoją właściwość, { &iface_type2} warning: initialization discards 'const' qualifier from pointer target type, co jest równoznaczne z deklaracją w postaci:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #8 18 Lis 2015 10:03
    grko
    Poziom 33  

    Zdefiniuj swoja strukture tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #9 18 Lis 2015 10:37
    yild
    Poziom 14  

    Nawet działa... dzięki :)

    0
  • #10 18 Lis 2015 14:23
    Freddie Chopin
    Specjalista - Mikrokontrolery

    yild napisał:
    Składniowo używam C do projektu, z uwagi na brak OOP...

    Zacznij używać C++ zamiast wynajdywać koło od nowa (;

    0
  • #11 20 Lis 2015 10:40
    yild
    Poziom 14  

    Freddie Chopin napisał:
    yild napisał:
    Składniowo używam C do projektu, z uwagi na brak OOP...

    Zacznij używać C++ zamiast wynajdywać koło od nowa (;


    I na tym się skończyło heh... ;)

    0