Joskus kahden eri ohjelmointikielen käyttö tuottaa yllättäviä tuloksia !
Tässä tapauksessa on c -kielellä tehty kirjasto (käännetty .so -kirjastoksi gcc:llä).
Pääohjelma on tehty FreePascal / Lazarus -yhdistelmällä.
Pääohjelma lataa tuon .so -kirjaston LoadLibrary ja hakee xmain -funktion osoitteen GetProcAddress -funktiolla.
FreePascal pyrkii tarjoamaan käyttöjärjestelmäriippumatont aohjelmointia niin pitkälle kuin mahdollista, niinpä nuo mainitut funktiot windowsissa ovat suoraan vastaavia winAPI -kutsuja, ja linuxissa ne ovat aliaksia dlopen() ja dlsym() -funktioille.
Tuo ohjelman ja .so:n yhdistelmä toimii oikein, kun antaa tulosten tulostua näytölle.
Sensijaan jos ohjelman ajaa näin:
ohjelma >lokitiedosto.txt
niin osa C -kielisen kirjaston tulosteista katoaa olemattomiin, ja lisäksi pääohjelman ja .so -kirjaston tulosteiden keskinäinen järjestys muuttuu yllättävästi!
C -kirjasto käyttää C:n kirjastofunktiota printf()
ja pääohjelma Objectpascalin Write ja WriteLn -proseduureja.
Ilmeisesti objectpascal -koodiin pitäisi lisätä jokin flush -kutsu ennen sellaisia .so -kirjastoon kohdistuvia funktiokutsuja, joiden sisällä tapahtuu printf() -kutsuja.
Ja vastaavasti ilmeisesti C -kielisissä funktioissa pitäisi kutsua jotakin flush -funktiota ennen paluuta (pääohjelmaan).
Muussa tapauksessa C -kielen stdout ja objectpascalin output -tiedostojen käsittely ilmeisesti jollain tavalla häritsevät toisiaan.
Eli: Mikä flush -kutsu ja miten sitä käytetään:
a) C -kielessä
ja
b) Objectpascalissa ?
Tässä tapauksessa on c -kielellä tehty kirjasto (käännetty .so -kirjastoksi gcc:llä).
Pääohjelma on tehty FreePascal / Lazarus -yhdistelmällä.
Pääohjelma lataa tuon .so -kirjaston LoadLibrary ja hakee xmain -funktion osoitteen GetProcAddress -funktiolla.
FreePascal pyrkii tarjoamaan käyttöjärjestelmäriippumatont aohjelmointia niin pitkälle kuin mahdollista, niinpä nuo mainitut funktiot windowsissa ovat suoraan vastaavia winAPI -kutsuja, ja linuxissa ne ovat aliaksia dlopen() ja dlsym() -funktioille.
Tuo ohjelman ja .so:n yhdistelmä toimii oikein, kun antaa tulosten tulostua näytölle.
Sensijaan jos ohjelman ajaa näin:
ohjelma >lokitiedosto.txt
niin osa C -kielisen kirjaston tulosteista katoaa olemattomiin, ja lisäksi pääohjelman ja .so -kirjaston tulosteiden keskinäinen järjestys muuttuu yllättävästi!
C -kirjasto käyttää C:n kirjastofunktiota printf()
ja pääohjelma Objectpascalin Write ja WriteLn -proseduureja.
Ilmeisesti objectpascal -koodiin pitäisi lisätä jokin flush -kutsu ennen sellaisia .so -kirjastoon kohdistuvia funktiokutsuja, joiden sisällä tapahtuu printf() -kutsuja.
Ja vastaavasti ilmeisesti C -kielisissä funktioissa pitäisi kutsua jotakin flush -funktiota ennen paluuta (pääohjelmaan).
Muussa tapauksessa C -kielen stdout ja objectpascalin output -tiedostojen käsittely ilmeisesti jollain tavalla häritsevät toisiaan.
Eli: Mikä flush -kutsu ja miten sitä käytetään:
a) C -kielessä
ja
b) Objectpascalissa ?
Vastaukset 9
Vanhimmat
vastaus / C-kieli
C -kielessä ongelma näköjään ratkeaa laittamalla jokaisen sellaisen pääohjelmasta kutsuttavan funktion viimeiseksi (juuri ennen return -lausetta) ohjelmakoodiriviksi tämä:
fflush(stdout);
joka (suoraan tai välillisesti) kutsuu printf() -funktiota siten, että tulostus menee standarditulostusvirtaan (stdout).
Objectpascalin osalta jää selvitettäväksi, tavitaanko vastaavaa toimenpidettä sielläkin, ja miten se siellä hoidetaan...
Pascal:ssa (Delphi,FreePascal,Lazarus...) on flush aliohjelma.
http://www.freepascal.org/docs-html/rtl/system/flush.html
Flush:in käytöstä...
Siis:
mikä on itseasiassa oikea sääntö flush:in käytöstä?
Käyttökohteena siis standarditulostevirta eli stdout (C) ja output (Objectpascal).
Kerrottakoon sen verran, että alunperin on ollut C -kielinen ohjelma, jonka olen itse muuntanut .so -kirjastoksi ja sitten olen itse kirjoitanut FreePascal Lazarus -yhdistelmällä ohjelman, joka käyttää tätä .so -kirjastoa.
Seuraavaksi olisi tarkoitus lisätä hyvin moneen kohtaan ko. C -koodia kutsu funktioon, joka on määritelty C:ssä funktiotyyppinä ja osoittimena funktioon, joka laitetaan osoittamaan FreePascalilla tehtyyn proseduuriin.
Koska kyseessä on Objectpascalissa proseduuri, niin luonnollisesti sen C -prototyypissä funktion paluuarvo on void.
funktio saa yhtenä argumenttina C-kääntäjän tarjoamana char* -tyyppisen viitteen, joka osoittaa AsciiZ -merkkijonoon, joka kertoo sen funktion nimen, josta käsin tätä apufunktiota kutsuttiin.
Lisäksi tarkoitus on välittää objectpascal -ohjelman tietoon osoitin varsin moneen alunperin C -ohjelman sisäiseen muuttujaan. Objectpascal -ohjelma ei kuitenkaan muuta ko. osoittimien osoittamaa tietoa, vaan lähinnä pasiivisesti tarkkailee muuttujien arvon muuttumista eri vaiheissa C -koodin suoritusta.
Kuitenkin, koska sekä alkuperäinen C -koodi että itse kirjoittamani objectpascal -koodi saattavat molemmat kirjoitella standardiin tulostusvirtaan, niin jotenkin pitäisi pitää huolta, etteivät sotke toisiaan.
Flush(Output);
Oletko käyttänyt Lazarusta myös gcc:n kanssa?
"Oletko käyttänyt Lazarusta myös gcc:n kanssa?"
Ei nyt sentään!
Vaan siis gcc:llä on vain käännetty c -kielistä lähdekoodia .so -dynaamiseksi kirjastoksi ja sitten Freepascal lazarus -yhdistelmällä koodatgtu ohjelma, joka käyttää tuon .so:n tarjoamia aliohjelmia.
Siis suoraan ei lazarus toimi gcc:n kanssa, mutta kaiken uuden koodaankin freepascalilla (Linux) tai Delphillä (Windows).
C -kielen ainoa tarve tulee siitä, että C:llä on valtavasti valmiiksi tehtyä koodia.
Mutta jos itse koodaan uutta, niin miksi koodaisin C:llä kun objectpascal on joka suhteessa helpompi ja monipuolisempi työväline.
Huhujen mukaan Lazaruksen alla oleva kääntäjä
voisi olla joku muukin kuin FPC!!!
Kannattaisi ottaa yhteyttä noihin Lazaruksen tekijöihin (esim. englannin kieliselle keskustelupalstalle tms). Selvittää millaisella vaivalla tuo Lazarus ympäristö hoitaisi molemmat käännökset. Voi olla hyvinkin mahdollista että saat todella hyviä vinkkejä sieltä.
Lue myös tämä
http://keskustelu.suomi24.fi/show.fcgi?category=108&conference=4500000000000646&posting=22000000042456541