Volání funkce z funkce – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Volání funkce z funkce – C / C++ – Fórum – Programujte.comVolání funkce z funkce – C / C++ – Fórum – Programujte.com

 

oxidián0
Grafoman
16. 6. 2016   #1
-
0
-

V opencv se občas objevují funkce, které se mají zavolat s argumentem funkce. Myslím že nemá smysl sem uvádět konkrétní kód, jde ale o princip. Je to případ kdy se tato funkce má rekurzivně volat. Argumenty tam nejsou, je tam pouze jméno funkce. Například dotyčný callback se má volat s několika argumenty jako je scale, delta apod. V příkladech které jsem viděl se to dělá tak, že si dané proměnné nastavíte globálně a pak je použijete a z mainu nebo odkud se zavolá funkce s callbackem. Uvnitř této funkce se pak porovnává ta globální proměnná a podle toho se vyhodnotí co dál...

Nechápu jakým způsobem se toto řeší pokud chcete psát složitější program kde není jedna funkce ale třeba 50 funkcí které slouží jako gragický filtr. Nebo v případě že toto chcete použít jako dll knihovnu. Tolik globálních proměnných by v programu vyvolalo dost velký chaos a v případě dll ještě větší.

Nahlásit jako SPAM
IP: 78.45.87.–
ondrej39+1
Věrný člen
16. 6. 2016   #2
-
0
-

#1 oxidián
To co ty zde uvádíš je úplně normální například v JavaScriptu nebo funkcionálním programování a má také co společného s event-driven programováním. Prostě zavoláš nějakou funkci A a předáš jí callback B jako parametr. Tento callback obsahuje tělo, které se má vykonat po (např.) úspěšném dokončení operace funkce A, co je ale super, že vůbec neřešíš, kdy se tak doopravdy stane.

Představ si to tak, že ta funkce A udává určitou šablonu, jak bude daná operace probíhat. V určitých chvílích jsi schopen zasáhnout do exekuce dané šablony, pokud ti to šablona umožní například implementací vlastního callbacku. Skvěle se tímto způsobem píší znovupoužitelné funkce, které mají šablonu stejnou, ale callback bude vždy jiný.

Nahlásit jako SPAM
IP: 79.141.243.–
Inject all the dependencies!
oxidián0
Grafoman
16. 6. 2016   #3
-
0
-

Dám sem kód

void on_trackbar( int, void* );

 Toto vytvoří posunovací lištu v okně. Jak budeš posouvat lištou, tak program se bude opakovaně spouštět a okno s grafikou se bude aktualizovat:

createTrackbar( "Max  corners:", source_window, &wrapper.arguments.maxCorners, wrapper.arguments.maxTrackbar, on_trackbar );

 Zobraz grafiku - proč tam je ten on_trackbar (0,0) nevím

imshow( source_window, src );
on_trackbar( 0, 0 );

ale je z toho patrné že tam nemohu dát další argumenty, aspoň tak to chápu.

Definice funkce:

void on_trackbar( int, void* )
{
  if( maxCorners < 1 ) { maxCorners = 1; }

  /// Parameters for Shi-Tomasi algorithm
  vector<Point2f> corners;
  double qualityLevel = 0.01;
  double minDistance = 10;
  int blockSize = 3;
  bool useHarrisDetector = false;
  double k = 0.04;

  /// Copy the source image
  Mat copy;
  copy = src.clone();

  /// Apply corner detection
  goodFeaturesToTrack( src_gray,
               corners,
               maxCorners,
               qualityLevel,
               minDistance,
               Mat(),
               blockSize,
               useHarrisDetector,
               k );


  /// Draw corners detected
  cout<<"** Number of corners detected: "<<corners.size()<<endl;
  int r = 4;
  for( int i = 0; i < corners.size(); i++ )
     { circle( copy, corners[i], r, Scalar(rng.uniform(0,255), rng.uniform(0,255),
              rng.uniform(0,255)), -1, 8, 0 ); }

  /// Show what you got
  namedWindow( source_window, WINDOW_AUTOSIZE );
  imshow( source_window, copy );
}


maxCorners je právě globální proměnná.


double qualityLevel = 0.01;

double minDistance = 10;

to by taky mělo být definované přes argumenty programu. Problém je ale v tom že já mám globální wrapper ve kterém mám argumenty. Wrapper bych chtěl předat jako třetí argument, ale nevím jestli toto nějak jde udělat.
 

Nahlásit jako SPAM
IP: 78.45.87.–
Kit+15
Guru
16. 6. 2016   #4
-
0
-

#3 oxidián
Tak ji zavoláš i s těmi parametry. V čem je problém?

Nahlásit jako SPAM
IP: 194.228.13.–
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
KIIV
~ Moderátor
+43
God of flame
16. 6. 2016   #5
-
0
-

z dokumentace:

C++: int createTrackbar(const string& trackbarname, const string& winname, int* value, int count, TrackbarCallback onChange=0, void* userdata=0)

Dulezita je tam ta cast "void * userdata"  - kam jen hodis pointer treba na ten wrapper (jen musis jeho adresu pretypovat na void pointer a pak v handleru zase nazpet)... Template, kde by si predal primo objekt implementujici operator(), by byl vyrazne univerzalnejsi. (Ale to by teoreticky slo udelat wrapperem - tentokrate pouziteho ve spravnem smyslu)

Nahlásit jako SPAM
IP: 212.47.3.–
Program vždy dělá to co naprogramujete, ne to co chcete...
oxidián0
Grafoman
17. 6. 2016   #6
-
0
-

Jak přetypovat? Nic než toto to nevezme:

createTrackbar( "Max  corners:", source_window, &wrapper.arguments.maxCorners, wrapper.arguments.maxTrackbar, 0, &wrapper );

chyba:

error C2664: 'cv::createTrackbar' : cannot convert parameter 5 from 'void (__cdecl *)(int,void *,Wrapper)' to 'cv::TrackbarCallback'

Cílový typ je void*

Navíc když dám do on_trackbar třetí argument Wrapper wrapper,

tak

createTrackbar( "Max  corners:", source_window, &wrapper.arguments.maxCorners, wrapper.arguments.maxTrackbar, on_trackbar );

přestane fungovat

 None of the functions with this name in scope match the target type

 a s tím to taky nejde:

createTrackbar( "Max  corners:", source_window, &wrapper.arguments.maxCorners, wrapper.arguments.maxTrackbar, on_trackbar, wrapper );

Nahlásit jako SPAM
IP: 78.45.87.–
KIIV
~ Moderátor
+43
God of flame
17. 6. 2016   #7
-
0
-

neco jako:
createTrackbar( "Max corners:", source_window, &wrapper.arguments.maxCorners, wrapper.arguments.maxTrackbar, on_trackbar, reinterpret_cast<void*>(&mojetrida) );
a v tom:

void on_trackbar(int, void* ptr) {

  MojeTrida * mojetrida = reinterpret_cast<MojeTrida*>(ptr);

Nahlásit jako SPAM
IP: 93.91.152.–
Program vždy dělá to co naprogramujete, ne to co chcete...
oxidián0
Grafoman
17. 6. 2016   #8
-
0
-

Díky moc, konečně to jede.

jaký je rozdíl mezi

reinterpret_cast<Wrapper*>(ptr)


a (Wrapper * ) ptr?

nebo

reinterpret_cast<void*>(&wrapper)

a

(void * ) &wrapper

?

Nahlásit jako SPAM
IP: 78.45.87.–
KIIV
~ Moderátor
+43
God of flame
17. 6. 2016   #9
-
0
-

V pripade reinterpret_cast tusim zrovna zadny. Akorat (void*)neco je styl z C. 

Nahlásit jako SPAM
IP: 93.91.152.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 16 hostů

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý