LINUX.ORG.RU

Вызвать метод динамически получая его имя.


0

0

Всем привет! Как в c++ можно выполнить следующие маневры. Например в программе есть функция


int test(int k,string d)
{
  return 0;
}


int main()
{
  // имя метода который нужно вызвать!
  string method "test";
  

  // и собственно вопрос как вызвать метод test если его имя получаю
  // через string
  return 0;
}

Без очень жёстких хаков - никак

runtime ★★★★
()

Определить метод в shared-library, а потом его оттудова импортировать таким макаром. В рамках одной программы без всяких заморочек - никак.

Насколько я знаю, в Qt можно вызвать метод класса, зная его имя в форме строки. Но не помню как.

shutty
()

Use dl, Luke

#include <stdio.h>
#include <dlfcn.h>

void hello(void)
{
        printf("Hello, world!\n");
}

void bye(void)
{
        printf("Bye, world!\n");
}

int main(int argc, char *argv[])
{
        void (*func)(void);
        void *handle;

        if (argc != 2)
                return 1;

        handle = dlopen(NULL, RTLD_NOW);
        if (handle == NULL) {
                printf("dlopen: %s\n", dlerror());
                return 1;
        }

        *(void **) &func = dlsym(handle, argv[1]);
        if (func == NULL) {
                printf("dlsym: %s\n", dlerror());
                return 1;
        }

        func();

        dlclose(handle);
        return 0;
}

mikeos[~]$ ./a.out hello
Hello, world!
mikeos[~]$ ./a.out bye
Bye, world!

anonymous
()

Не проще ли сделать что-то по типу:

int main()
{
  ...
  switch(string)
  {
  case "tes1": test1(...);
    break;
  case "test2": test2(...);
    ...
}
Zodd ★★★★★
()
#include <boost/function.hpp>
#include <boost/bind.hpp>
...
map<string, boost::function<void (vector<string>&) > > commands;
...
void ArchSession::cmdControl(vector<string> &args);
...
commands["GETSTREAM"] = boost::bind(&ArchSession::cmdGetStream, this, _1);
commands["CONTROL"]   = boost::bind(&ArchSession::cmdControl, this, _1);
commands["SHUTDOWN"]  = boost::bind(&ArchSession::cmdShutdown, this, _1);
...
if (commands[cmd])
        commands[cmd](args);
mv ★★★★★
()
Ответ на: комментарий от k_andy

Это и в винде будет работать. Где-то на гуглокоде есть библиотека dl под винлу. Транслирует вызовы dl*() в winAPI. Пользовался пару раз.

staseg ★★★★★
()
Ответ на: комментарий от mv

Хе-хе. Никак, вестимо. :) Пусть ТС сам выбирает, что же он хочет методы (как он написал) или процедуры (какой пример он привёл).

k_andy ★★★
()
Ответ на: комментарий от staseg

Это и в винде будет работать. Где-то на гуглокоде есть библиотека dl под винлу. Транслирует вызовы dl*() в winAPI. Пользовался пару раз.

Нафига оно вообще надо, если с плюсовыми методами не работает, не кроссплатформенно, и в самих плюсах есть гораздо более лаконичные решения этого вопроса, работающие везде?

mv ★★★★★
()
Ответ на: комментарий от malik555

А для чего такое может понадобится, что нельзя обойтись простыми средствами? Зачем такие извращения?

Zodd ★★★★★
()
Ответ на: комментарий от mv

>>Очень интересно посмотреть, как вы с помощью dl будете загружать плюсовые методы ;)

Можно, конечно, завернуть в extern «C», но проще это сделать через map, конечно же.

MuZHiK-2 ★★★★
()

Если при разработке возникают такого рода задачи, то это верный признак серьёзных недочётов на стадии проектирования. Грамотной реализацией такой потребности будет применение объектов-функций (см. «ЯП С++» Б. Страуструб 18.4 и 25.5).

Так что если вас по работе заставляют писать такой вульгарный код, лучше не ищите способа подстановки костылей, ищите нового работодателя.

anonymous
()
Ответ на: комментарий от mv

>Нафига оно вообще надо, если с плюсовыми методами не работает, не кроссплатформенно, и в самих плюсах есть гораздо более лаконичные решения этого вопроса, работающие везде?

По-моему по хорошему такой задачи вообще не должно возникать, а с плюсовыми методами - и подавно. Я лишь заметил, что под винду такой костыль сработает.

staseg ★★★★★
()
Ответ на: комментарий от malik555

В поддержку решения от Zodd — примерно так и работает Qt. moc что-то подобное и генерит.

vaulter
()
Ответ на: комментарий от anonymous

> Если при разработке возникают такого рода задачи, то это верный признак серьёзных недочётов на стадии проектирования.

Я бы даже сказал, если автору нужно интенсивно решать такого рода задачи, то следует подумать о выборе другого языка.

runtime ★★★★
()

http://cpptcl.sourceforge.net/

берёшь вот это, встраиваешь интерпретатор размером в ~800KB в приложение, и получаешь набор динамических возможностей с прозрачным интерфейсом к C++. на правах рекламы, так сказать

jtootf ★★★★★
()
Ответ на: комментарий от Cy6erBr4in

есть более удобные инструменты для подобных занятий

я тоже :)

jtootf ★★★★★
()
sub test {print 'hello'};
$sub_name = 'test';
&$sub_name();
anonymous
()
Ответ на: комментарий от anonymous

А чё «TEST», а не «test»? Lips не чувствителен к регистру?

Внутри CL символы capitalized. Поэтому либо (string-upcase ...), либо сразу большими буквами.

* (intern "hello")

|hello|
NIL
* (intern "HELLO")

HELLO
NIL

mv ★★★★★
()
Ответ на: комментарий от mv

> Поэтому либо (string-upcase ...), либо сразу большими буквами.

либо забить на строки и юзать сразу символы, не?

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

либо забить на строки и юзать сразу символы, не?

Да. Но у ТС строки :)

mv ★★★★★
()
Ответ на: комментарий от anonymous

Ну а если бы я назвал функцию не test, а Test, как бы он «внутри» провёл различие?

intern капитализацию не делает. Символы, интернированные из test, Test, TEST, tEsT будут разными.

mv ★★★★★
()
Ответ на: комментарий от anonymous

> Т.е. CL таки не различает регистр в функциях? А в переменных?

CL не различает регистр в символах. точнее приводит имена символов к верхнему регистру. если только не указать ему этого не делать, с помощью экранирования:

test == |TEST|

\test == |tEST|

t\e\s\t == |Test|

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_
CL-USER> (symbol-name 'test)
"TEST"
CL-USER> (symbol-name '\test)
"tEST"
CL-USER> (symbol-name 't\e\s\t)
"Test"
CL-USER> (symbol-name '|Test|)
"Test"
CL-USER> (intern "Test")
|Test|
:INTERNAL
CL-USER> 
korvin_ ★★★★★
()
Ответ на: комментарий от anonymous

Не догоняю, перепиши эту строчку для случая названия функции не test, а Test:

(funcall (intern «TEST») bla bla))

(funcall (intern (string-upcase «Test»)) bla bla)

mv ★★★★★
()
Ответ на: комментарий от korvin_

Получается если у меня две функции test и Test, чтобы вызвыать вторую надо всегда экран ставить? Зачем такое черезжопие?

anonymous
()
Ответ на: комментарий от anonymous

> Получается если у меня две функции test и Test, чтобы вызвыать вторую надо всегда экран ставить? Зачем такое черезжопие?

а зачем тебе две функции test и Test? зачем такое черезжопие? =)

korvin_ ★★★★★
()
Ответ на: комментарий от korvin_

Черезжопие какраз начинается, когда система не видит различия в названиях функция и следует этой «мягкой» политике. Можно очепятаться, а добрый компилятор проглотит и не укажет на ошибки. Какой-ть Страуструб бы проблевался от такого поведения.

anonymous
()
Ответ на: комментарий от anonymous

> Черезжопие какраз начинается, когда система не видит различия в названиях функция и следует этой «мягкой» политике. Можно очепятаться, а добрый компилятор проглотит и не укажет на ошибки. Какой-ть Страуструб бы проблевался от такого поведения.

лол. пример опечатки покажи?

а страуструп пусть поблюёт, ему полезно

korvin_ ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.