Mietin tuossa, pitääko uniteissa käyttää aina funktio-rajapintaa vai
voiko olla myös globaaleja muuttujia? Ts. mitkä ovat muuttujien näkyvyysalueet uniteissa? Tuolla esimerkissä ainakin kaikki oli funktioissa:
https://www.tutorialspoint.com/pascal/pascal_units.htm
Unittien näkyvyysalueet?
3
286
Vastaukset
- Anonyymi
Funktion sisällä määritellyt on funktion paikallisia, yksikössä (unit) määritellyt muuttujat tavoittaa kaikki yksikön sisältämät funktiot ja procedure rutiinit.
Esimerkki:
var a : string;
implementation
var s : string;
procedure gg;
var t :string;
begin
end.
function ff;
var x : string
begin
end
a -muuttuja näkyy myös muille yksiköille, ja s näkyy vain tässä yksikössä, t -muuttuja näkyy vain gg-rutiinin sisällä ja x -muuttuja näkyy vain ff -funktion sisällä.- Anonyymi
Anonyymi (18.10.2021 17:52) on aivan oikeassa -juuri näin.
Pääsääntö: Globaalit muuttujat ovat huono ohjelmointitapa, ja niiden käyttöä on pääsääntöisesti vältettävä.
Mutta joissain erityistapauksissa Globaalit muuttujat ovat hyvä ja tarpeellinen idea.
Kannattaa myös huomata:
Virallisesti Windows API ja DLL:t eivät ole koskaan tukeneet muuttujien exportointia / importointia !
Jotkut vapaan lähdekoodin ohjelmat ovat ilmeisesti väärinkäyttäneet funktioiden exportointia siten, että on exportoitu muuttujan osoite ikään kuin se olisi funktion osoite.
JOS esim. C -kielellä tehdyssä DLL:ssä on näin tehty, oma suositukseni on:
Oletetaan, että muuttujan nimi on X ja se on C-kielellä int -tyyppiä.
Jos se on exportoitu nimellä X, toimi näin:
Unit something;
interface
function GetAddressOfX:Pointer;
implementation
function X(); cdecl; external 'Libary_Made_In_C.DLL';
function GetAddressOfX:Pointer;
begin
Result := @X;
end;
Kutsumalla funktiota GetAddressOfX, se palauttaa Pointer -tyyppisen osoittimen, joka osoittaa tuohon sääntöjen vastaisesti exportoituun muuttujaan X.
Voit sitten tehdä näin:
var
P : PInteger;
begin
P := GetAddressOfX;
end;
esim. ns. singleton -luokan osalta voisi olla hyvä idea:
globaali muuttuja:
var
MySingleton : TMySingleton;
SingletonTeardown : Boolean;
ja sitten:
initialization
MySingleton : TMySingleton.Create( {parametrit tähän, jos niitä on} );
finalization
SingletonTeardown := True;
FreeAndNil(MySingleton);
end.
1-säikeisessä ohjelmassa tämä riittääkin.
Monisäikeisessä ohjelmassa pitää vielä miettiä, miten voit toisesta säikeestä turvallisesti käyttää MySingleton -muuttujan viittaamaa TMySingleton -tyyppistä luokkaa - kas kun se olio voi yht'äkkiä kadota, kun toinen säie päätyy tuohon
FreeAndNil(MySingleton); -kohtaan !
Monisäikeinen ohjelmointi ei tämän takia aina ole helppoa eikä yksinkertaista.
Pitäisikö kaikki TMySingleton -luokan metodit koodata näin:
procedure TMySingleton.Esimerkki;
begin
FSingletonLock.Acquire;
try
// tee varsinainen asia tässä
finally
FSingletonLock.Release;
end;
end;
Tuo muuten toimisi, mutta tuo FreeAndNil -käskyn jälkeen mitään TMySingleton -luokan metodia ei saisi kutsua ! - Anonyymi
Anonyymi kirjoitti:
Anonyymi (18.10.2021 17:52) on aivan oikeassa -juuri näin.
Pääsääntö: Globaalit muuttujat ovat huono ohjelmointitapa, ja niiden käyttöä on pääsääntöisesti vältettävä.
Mutta joissain erityistapauksissa Globaalit muuttujat ovat hyvä ja tarpeellinen idea.
Kannattaa myös huomata:
Virallisesti Windows API ja DLL:t eivät ole koskaan tukeneet muuttujien exportointia / importointia !
Jotkut vapaan lähdekoodin ohjelmat ovat ilmeisesti väärinkäyttäneet funktioiden exportointia siten, että on exportoitu muuttujan osoite ikään kuin se olisi funktion osoite.
JOS esim. C -kielellä tehdyssä DLL:ssä on näin tehty, oma suositukseni on:
Oletetaan, että muuttujan nimi on X ja se on C-kielellä int -tyyppiä.
Jos se on exportoitu nimellä X, toimi näin:
Unit something;
interface
function GetAddressOfX:Pointer;
implementation
function X(); cdecl; external 'Libary_Made_In_C.DLL';
function GetAddressOfX:Pointer;
begin
Result := @X;
end;
Kutsumalla funktiota GetAddressOfX, se palauttaa Pointer -tyyppisen osoittimen, joka osoittaa tuohon sääntöjen vastaisesti exportoituun muuttujaan X.
Voit sitten tehdä näin:
var
P : PInteger;
begin
P := GetAddressOfX;
end;
esim. ns. singleton -luokan osalta voisi olla hyvä idea:
globaali muuttuja:
var
MySingleton : TMySingleton;
SingletonTeardown : Boolean;
ja sitten:
initialization
MySingleton : TMySingleton.Create( {parametrit tähän, jos niitä on} );
finalization
SingletonTeardown := True;
FreeAndNil(MySingleton);
end.
1-säikeisessä ohjelmassa tämä riittääkin.
Monisäikeisessä ohjelmassa pitää vielä miettiä, miten voit toisesta säikeestä turvallisesti käyttää MySingleton -muuttujan viittaamaa TMySingleton -tyyppistä luokkaa - kas kun se olio voi yht'äkkiä kadota, kun toinen säie päätyy tuohon
FreeAndNil(MySingleton); -kohtaan !
Monisäikeinen ohjelmointi ei tämän takia aina ole helppoa eikä yksinkertaista.
Pitäisikö kaikki TMySingleton -luokan metodit koodata näin:
procedure TMySingleton.Esimerkki;
begin
FSingletonLock.Acquire;
try
// tee varsinainen asia tässä
finally
FSingletonLock.Release;
end;
end;
Tuo muuten toimisi, mutta tuo FreeAndNil -käskyn jälkeen mitään TMySingleton -luokan metodia ei saisi kutsua !Korjaus edelliseen:
"
implementation
function X(); cdecl; external 'Libary_Made_In_C.DLL';
function GetAddressOfX:Pointer;
begin
Result := @X;
end;
Kutsumalla funktiota GetAddressOfX, se palauttaa Pointer -tyyppisen osoittimen, joka osoittaa tuohon sääntöjen vastaisesti exportoituun muuttujaan X.
"
TEORIASSA tuon pitäisi toimia.
Mutta veikkaanpa, ettei oikeasti toimi, ja siihen on syykin, miksei toimi.
Tuo johtuu siitä, että tuo lause:
Result := @X;
palauttaa kylläkin muistiosoitteen (mutta todennäköisesti väärän asian muistiosoitteen) ja palauttaa tuon muistiosoitteen GetAddressOfX:Pointer -funktion tuloksena.
Ongelma liittyy tapaan, jolla ainakin Delphi (ja mahdollisesti myös FreePascal) importoi funktioita DLL;stä, jos ei käytetä ajonaikaista importointitapaa eli LoadLibrary() ja GetProcAddress().
Helpoin tapa kiertää ongelma on nimenomaan käyttää ajonaikaista importointitapaa eli LoadLibrary() ja GetProcAddress() -funktioita, tällöin homma toimii oikein.
JOS noin ei halua tehdä, kyllä olisi mahdollista kirjoittaa funktio, joka tekee silti oikean asian, mutta se funktio ei ole ihan noin yksinkertainen kuin edellisessä viestissä on esitetty.
Ketjusta on poistettu 0 sääntöjenvastaista viestiä.
Luetuimmat keskustelut
SDP haluaa LISÄÄ veroja bensa-autoille!
Sdp:n vaihtoehtobudjetti esittää polttomoottoriautoille lisää veroja Sdp esittää tuoreessa vaihtoehtobudjetissaan verot527173Mies, näen sinua hetken
ja olet mielessä ikuisuuden. Toisia näen ikuisuuden ja he eivät jää mieleen hetkeksikään. Muistan jokaisen kohtaamisen254499Riikka se jytkytti BKT:stä nyt 0,3 prosenttia pois
Ja vain kolmessa kuukaudessa! Vuositasollahan tuo tarkoittaa reilun prosentin pudotusta. Pärjäisi varmaan lasketteluss164190Riikan perintö: ennätysvelka, ennätystyöttömyys ja ennätysverotus
Tavallisen keskituloisen suomalaisen verotus on kireintä vuosikymmeniin, ja ensi vuonna palkansaajien käteen jää vieläki2303804Antti Lindtman kiitti valtiovarainministeri Purraa
Ministeri Purra kertoi ottavasa vastuun EU:n alijäämämenettelyyn joutumisesta. Hän myös sanoi tietävänsä, että Lindtman293073Suomalaisten enemmistö on (ateisteja / fiksuja / sosialisteja)
Tai jokin noiden yhdistelmä, koska S-ryhmän markkinaosuus päivittäistavarakaupasta on yli 50 prosenttia.132776Riikka Purra on ihana, jämpti
Hän yrittää saada Suomen taas kuntoon. Sanoo asiat suoraan, eikä piiloudu kapulakielen taakse. Riikan kaltaisia päättä1082728"Purra löylytti oppositiota", sanoi naistoimittaja Pöllöraadissa
Kyllä, Purra tekee juuri sitä työtä mitä hänen tuossa asemassa pitää tehdä, hän antaa oppositiolle takaisin samalla mita432413Henkilökohtaisia paljastuksia Dubaista - Kohujulkkis Sofia Belorf on äitipuoli ja puoliso!
Tiesitkö, että Sofia on äitipuoli ja rakastava puoliso? Sofia Belorf saa oman sarjan, jossa seurataan hänen Bling Bling672381K-kauppa on liian kallis. Ei voi S-ryhmäläinen siirtyä tuonne asiakkaaksi
Hintatason ero K-kauppojen ja S-markettien välillä on niin suuri, että S-market ei juurikaan menetä asiakkaitaan K-ketju1001970