kategoria: ANSI C
[#1] [C]Odczytanie argumentów programu
Cześć Koledzy i Koleżanki,

Ostatnio używam sobie na mojej A600/020 AmigaOS 3.2, wszystko chodzi ładnie ale brakuje małego programu do rozpakowywania podobnego do UnArc (na aminecie jest MuiUnArc ale to zuo). Postanowiłem napisać prosty tool który będzie miał dwa pola do wyboru 1. archiwum, 2. dokąd rozpakować. Poza tymi inputami będzie przycisk rozpakuj. Plan jest/był taki żeby użyć xadmaster library z aminetu. Niestety nie doszedłem do momentu w któym powinienem wykorzystać ową bibliotekę ponieważ wywalam się na odczycie parametrów programu. Zgodnie z opisem znalezionym w necie i przykladami parametry powinny byc, co robię źle? Do postu dołączam screenshoty oraz linkuje niedziałający kod. Na jednym screenshocie debuguje i definitywnie cos jest nie tak bo argc == 3 ale ilosc argumentow w tablicy argv == 1. To jest bez sensu. Może ktoś z większym doświadczeniem powie co robie nie tak. Dodam że problem występuje również podczas startu z wb, wtedy w strukturze WBStartup wartośc sm_NumArgs == 0.





https://gist.github.com/jarokuczi/6f05f863becc67b8303818f4a1bc46ab

--update skompilowałem inny program, również z neta i on też nie odczytuje parametrów

Ostatnia aktualizacja: 25.08.2021 23:17:40 przez jarokuczi
[#2] Re: [C]Odczytanie argumentów programu

@jarokuczi, post #1

Nie znam się za bardzo na C.... Ale użycie funkcji ReadArgs może okazać się prostsze niż kopanie się z tego rodzaju problemami.
Chociaż z drugiej strony warto to rozgryźć i się czegoś nauczyć. Powodzenia życzę w kazdym radzie OK
[#3] Re: [C]Odczytanie argumentów programu

@jarokuczi, post #1

Zakomentuj RDARGS_OPTIONS i sprawdz ponownie.
[#4] Re: [C]Odczytanie argumentów programu

@jarokuczi, post #1

Też bym użył ReadArgs(). Trzeba zacząć od wzorca. Masz dwa parametry: ścieżka do archiwum, która jest tekstem i parametrem obowiązkowym, oraz katalog docelowy, który też jest tekstem i załóżmy, że też jest parametrem obowiązkowym. Wzorzec będzie zatem wyglądał tak:
"ARCHIVE/A,DEST/A"
Nazwy we wzorcu są nieistotne, ale wzorzec jest wyświetlany użytkownikowi, gdy poda "?" jako argument, więc dobrze by było, żeby coś mówiły o argumentach. "/A" oznacza, że argument jest wymagany. Następnie tworzymy tablicę LONG-ów, w której znajdą się wyniki. Mamy 2 argumenty, więc tablica będzie miała 2 elementy:
LONG values[2];
Po udanym wykonaniu funkcji w tej tablicy znajdą się wskaźniki na teksty - wartości argumentów. Pamięć na nie została zaalokowana automatycznie, więc trzeba ją potem zwolnić za pomocą FreeArgs().
struct RDArgs *rda;
LONG values[2];

if (rda = ReadArgs("ARCHIVE/A,DEST/A", values, NULL))
{
    printf("Argumenty: %s, %s\n", (STRPTR)values[0], (STRPTR)values[1]);
    FreeArgs(rda);
}


Ostatnia aktualizacja: 26.08.2021 08:11:15 przez Krashan
2
[#5] Re: [C]Odczytanie argumentów programu

@Krashan, post #4

Dziękuje wszystkim za odpowiedzi. Kwestia z ReadArgs brzmi sensownie, sprawdzę to po południu. Czy to pomoże również w odczytaniu parametrów gdy program uruchomiony jest z pod workbencha? Jak ewentualnie podejść do tematu odczytu parametrów z wb. Plan jest taki żeby podpiąć mój program jako tool dla archiwów i po kliknięciu w archiwum ma pojawić się gui, wtedy nazwe pliku archiwum muszę odczytać z parametru a miejsce docelowe będę chciał odczytać z tooltype.

Ostatnia aktualizacja: 26.08.2021 09:00:55 przez jarokuczi
[#6] Re: [C]Odczytanie argumentów programu

@jarokuczi, post #5

O ile pamętam, to argumenty uruchomienia z poziomu WB trzeba pobrać.. z tooltypów ikonki..
[#7] Re: [C]Odczytanie argumentów programu

@jarokuczi, post #5

Plan jest taki żeby podpiąć mój program jako tool dla archiwów i po kliknięciu w archiwum ma pojawić się gui, wtedy nazwe pliku archiwum muszę odczytać z parametru a miejsce docelowe będę chciał odczytać z tooltype.
Wtedy działasz inaczej. W strukturze WBStartup jest pole sm_ArgList, które jest wskaźnikiem na tablicę struktur WBArg. W przypadku kiedy Twój program został wywołany przez kliknięcie ikony typu "project", będąc wpisanym jako "default tool", w drugim elemencie tej tablicy (sm_ArgList[1]) będziesz miał strukturę WBArg z polami jak niżej:
  • wa_Name = nazwa pliku, do którego odnosi się kliknięta ikona
  • wa_Lock = lock na katalogu, w którym znajduje się ten plik
Żeby zaś się dobrać do tooltypów, to icon.library/GetDiskObject() i eksplorujesz do_ToolTypes.

Ostatnia aktualizacja: 26.08.2021 09:41:40 przez Krashan
[#8] Re: [C]Odczytanie argumentów programu

@Krashan, post #7

W moim programie uzyskuje wskaznik do struktury WBStartup uzywajac wskaznika na argv w lini 197 wklejonego kodu:

rc = wbmain((struct WBStartup *)argv);


Podczas startu z wb poprzez klikniecie w ikone archiwum dla ktorego default tool jest zdefiniowany moj prgram ilosc argumentow to 0 w strukturze WBStartup. No chyba że ma to związek z błędnym użyciem ReadArgs ale chyba nie bo ReadArgs uzywam podczas startu z shell.
[wyróżniony] [#9] Re: [C]Odczytanie argumentów programu

@jarokuczi, post #8

Według mnie to powinien być jakiś problem z kodem startowym, który dostarcza kompilator. To kod startowy zajmuje się prawidłowym wypełnieniem argc i argv.

sm_NumArgs przy starcie z WB musi być co najmniej 1. Pierwszym argumentem jest zawsze sam program narzędziowy.

Podobnie jeżeli argc > 0 (startujemy z DOS), to wówczas pierwszym argumentem argv[0] powinna być nazwa samego programu wykonywalnego.

Ostatnia aktualizacja: 26.08.2021 10:19:30 przez Hexmage960
[#10] Re: [C]Odczytanie argumentów programu

@jarokuczi, post #8

rc = wbmain((struct WBStartup *)argv);

Moim zdaniem to nie ma prawa działać. Nie można mieszać posixowych standardów z amigowym API. argv to tablica wskaźników na stringi, a struct WBStartup to struktura...
[#11] Re: [C]Odczytanie argumentów programu

@Krashan, post #10

Jak w takim razie poprawnie uzyskać wskaźnik na WBStartup?

Używałem tego przykładu:
http://amigadev.elowar.com/read/ADCD_2.1/Libraries_Manual_guide/node05C4.html

Ostatnia aktualizacja: 26.08.2021 11:01:52 przez jarokuczi
[#12] Re: [C]Odczytanie argumentów programu

@jarokuczi, post #11

Moze podam przyklad jakiego ja uzywam w swoich programach
#define TEMPLATE "SPACE/N/K,PICTURE/K,SIZE/N/K,STATIC/N/K"

LONG args[]={ (LONG)&Odstep,
              NULL,
              (LONG)&SkalaIkon,
              (LONG)&Statik};


        struct RDArgs *rda=NULL;
        struct DiskObject *dob=NULL;
        BPTR out;

                if (argc)
                {
                        if (!(rda=ReadArgs(TEMPLATE, args, NULL)))
                        {
                                PrintFault(IoErr(), argv[0]);
                                return 10;
                        }

                        out=Output();
                }
                else
                {
                        struct WBStartup *wbs=(struct WBStartup*)argv;
                        struct WBArg *wba=&wbs->sm_ArgList[wbs->sm_NumArgs-1];
                        BPTR oldcd;

                        if (!(*wba->wa_Name)) return 10;

                        oldcd=CurrentDir(wba->wa_Lock);
                        if ((dob=GetDiskObjectNew(wba->wa_Name)))
                        {
                                STRPTR str;

                                if ((str=FindToolType(dob->do_ToolTypes, "DELAY")))
                                        *(ULONG*)args[ARG_SPACE]=(ULONG)atoi(str);

                                if ((str=FindToolType(dob->do_ToolTypes, "PICTURE")))
                                {
                                        args[ARG_PICTURE]=(LONG)str;
                                        Obrazek = TRUE;
                                }

                                if ((str=FindToolType(dob->do_ToolTypes, "SIZE")))
                                        *(ULONG*)args[ARG_SIZE]=(ULONG)atoi(str);

                                if ((str=FindToolType(dob->do_ToolTypes, "STATIC")))
                                        *(ULONG*)args[ARG_STATIC]=(ULONG)atoi(str);

                        }

                        CurrentDir(oldcd);
                        outt=TRUE;
                }

                if (out || outt)
                {
                        sprintf(nazwa_podkladu, "%s", (STRPTR)args[ARG_PICTURE]);
                        Odstep = *(LONG*)args[ARG_SPACE];
                        Statik = *(LONG*)args[ARG_STATIC];
                        SkalaIkon = *(LONG*)args[ARG_SIZE];
                }
                if (rda) FreeArgs(rda);
                if (dob) FreeDiskObject(dob);

//printf("podano opcje: SPACE=%d, PICTURE=%s, STATIC=%d, SIZE=%d\n", Odstep, nazwa_podkladu, Statik, SkalaIkon);
[#13] Re: [C]Odczytanie argumentów programu

@Krashan, post #10

To jest poprawnie - przynajmniej większość Amigowych kompilatorów to w ten sposób obsługuje.

Jeżeli argc > 0, to program jest uruchamiany z DOS i argv to tablica stringów.

Jeżeli argc == 0, to program jest uruchomiony z WB i argv to adres struktury WBStartup.

Ostatnia aktualizacja: 26.08.2021 11:40:07 przez Hexmage960
[#14] Re: [C]Odczytanie argumentów programu

@jarokuczi, post #11

W tym kodzie jest komentarz:

in SAS/Lattice, argv is a pointer to the WBStartup message when argc is zero.

Czyli owszem, kompilatory Lattice i SAS/C jeżeli program jest odpalony z ikony wstawiają adres WBStartup w argv. Czy robi tak GCC i VBCC? Wątpię. Nie wiem też czym kompilujesz.

Ja używam własnego kodu startowego i sam odbieram WBStartup z portu procesu.
[#15] Re: [C]Odczytanie argumentów programu

@Krashan, post #14

Kompiluje gcc od bebbo:
https://github.com/bebbo/amiga-gcc
[#16] Re: [C]Odczytanie argumentów programu

@jarokuczi, post #1

Po pracy zbadałem temac uwzględniając wasze komentarze i problemem okazał się newliwb z którym domyślnie linkuje gcc. Po zmianie na libnix parametry zaczęły działać jak należy. Dziękuje wszystkim za pomoc.

@Phibrizzo: dzięki za fajny przykładzik, wykorzystałem wiedzę żeby szybko odczytać tool typy.

[#17] Re: [C]Odczytanie argumentów programu

@jarokuczi, post #16

No to jak widzę problem rozwiązany szeroki uśmiech
Mimo wszystko użycie ReadArgs ma tą zaletę że powinno działać z każdym kompilatorem i opcjami linkera.

Ostatnia aktualizacja: 26.08.2021 22:26:46 przez pisklak
1
Na stronie www.PPA.pl, podobnie jak na wielu innych stronach internetowych, wykorzystywane są tzw. cookies (ciasteczka). Służą ona m.in. do tego, aby zalogować się na swoje konto, czy brać udział w ankietach. Ze względu na nowe regulacje prawne jesteśmy zobowiązani do poinformowania Cię o tym w wyraźniejszy niż dotychczas sposób. Dalsze korzystanie z naszej strony bez zmiany ustawień przeglądarki internetowej będzie oznaczać, że zgadzasz się na ich wykorzystywanie.
OK, rozumiem