Wpis z mikrobloga

Drugie pytanie na dziś. Dotyczy #programowanie #cplusplus #cpp i bibliotek dunamicznie dołączanych pod #linux .
Mam kawałek kodu o zrozumienia. command4move.so to biblioteka z klasą command4move która dziedziczy po klasie Command.
...
#include "command.hh"
...

int main()
{
void *pLibHnd_Move = dlopen("command4move.so",RTLD_LAZY);
Command *(*pCreateCmd_Move)(void);
void *pFun;
if (!pLibHnd_Move) {
cerr << "!!! Brak biblioteki: command4move.so" << endl;
return 1;
}
pFun = dlsym(pLibHnd_Move,"CreateCmd");
if (!pFun) {
cerr << "!!! Nie znaleziono funkcji CreateCmd" << endl;
return 1;
}
pCreateCmd_Move = *reinterpret_cast(&pFun);
Command *pCmd = pCreateCmd_Move();

W klasie Command mam metodę statyczną static Command* CreateCmd(); rozwijaną jako:

Command* Command4Move::CreateCmd()
{
return new Command4Move();
}

Oraz w bibliotece command4move.so mam coś takiego:

extern "C" {
Command* CreateCmd(void);
}
Command* CreateCmd(void)
{
return Command4Move::CreateCmd();
}

Moim problemem jest zrozumienie co się dzieje w mainie i jakie rzutowania tam zachodzą.

  • 7
rozumiem że największe problemy z deklaracja:
Command *(*pCreateCmdMove)(void);
pCreateCmd
Move - jest wskaźnikiem na funkcję nie przyjmującą argumentów i zwracającą Command*

oraz z linią:
pCreateCmd_Move = *reinterpret_cast(&pFun);
wyłuskany, za pomocą operatora &, adres pFun (cokolwiek to jest) jest przerzutowany na wskaźnik na wskaźnik na funkcję (o deklaracji Command*(void)). spod tego wskaźnika jest wzięty jest adres funkcji który przypisany jest do pCreateCmd_Move.

tę linię dla większej czytelności można robić na coś takiego:
Command (pCreateCmdMove)(void);

@inplaz: W tej linijce pCreateCmdMove jest dopiero deklarowane? Nigdzie wcześniej się nie pojawia coś takiego.

dlsym zwraca wskaźniki tylko do funkcji które są wystawiane przy użyciu extern "C" ?
linijki pCreateCmd_Move = *reinterpret_cast(&pFun); ciągle nie łapię, ale na koniec pCmd jest tym co zwróciło wykonanie Command4Move::CreateCmd()
@kiciek: tak to jest deklaracja zmiennej pCreateCmdMove. deklaracje wskaźników na funkcje nie są zbyt przyjazne w odczycie, więc warto użyć std::function czy using.
zaktualizowałem poprzedni komentarz i rozłożyłem tę linijkę na części, jak czegoś nie łapiesz pytaj.
@inplaz:
Widzę do czego dążymy. Żeby się dało stosować pCreateCmd_Move jak normalną funkcję.

dlsym zwracający void* daje w tym wywołaniu wskaźnik na funkcję Command* CreateCmd(void) z dołączonej biblioteki, i nie można go jeszcze stosować, bo nie ma tutaj określonych typów. Chociaż wskazuje na coś konkretnego jest traktowany jaki void*.
Przy rzutowaniu ADRES (wskaźnika na void) jest rzutowany na WSKAŹNIK (na wskaźnik na funkcję). Miesza mi się w tej chwili różnica między