2013-03-12 5 views
1

Я хотел бы вызвать динамические функции C (например, форму stdlib, math ...). Это означает, что моя программа C знает только указатель на случайную функцию (например, printf) и свою подпись (закодированную как массив символов: char *, ...).C - вызов динамической функции без указателя функции

Моя цель в reflectCall-функцию, которая получает указатель на функцию (&printf), подпись (каким-то образом кодируется в char[]), а также параметры в виде long[] (long не фактический тип данных, один длинный значение может также представляют собой двойное значение, указатель, ...).

Подпись моего отражения функции поэтому выглядит следующим образом:

long reflectCall(void *funcPointer, char[] types, long[] args) 

Функция должна сделать фактический вызов функции *funcPointer и, наконец, вернуть результат.

В результате я могу не создать указатель указателя; например как этот:

int (*functionPtr)(int,int); 

Может кто-нибудь дать мне подсказку, как решить эту проблему или предложить любую справочную реализацию?

+0

Там в основном не способ сделать это в платформо-независимым способом. –

+0

Извините, вы не можете передавать varargs в функцию varargs портативно. C просто не поддерживает необходимое отражение. – nneonneo

ответ

4

C не предоставляет возможности для этого. Вам нужно будет написать тело функции в платформе ASM.

+0

Возможно, представляет интерес: [libffi] (http://sourceware.org/libffi/). – duskwuff

+0

Могу ли я это отразить с помощью C++? (я все еще хочу называть функции C) – matg

+0

@matg: Nope .... –

2

Как объяснено в другом месте, нет никакого способа сделать это по-настоящему динамически. Однако, если вы хотите построить таблицу функций с помощью указателей и использовать какую-то строку или индекс для описания того, что вы хотите сделать, это, безусловно, возможно, переносимым образом. Это совсем не редкость как решение для различного синтаксического анализа и другого «кода запуска на основе команд и т. Д.».

Но для этого требуется, чтобы вы использовали какой-либо указатель на функцию [или внесли свой void * в один в какой-то момент]. Нет другого (даже почти) портативного способа динамического вызова функции в C.

5

Можно сделать это в чистом C, но это не так просто и не так быстро:

  1. Создание функции-обертки для всех функций, которые вы хотите позвонить, такие как:

    int WrapPrintf(const char* types,long* args,long* results) 
    { 
        // Function specific code, in this case you can call printf for each parameter 
        while(*types) 
        { 
         switch(*types){ 
         case 'i': 
          printf("%d",(int)*args); 
          break; 
         case 'c': 
          printf("%c",(char)*args); 
          break; 
         // .. and so on 
         } 
    
         ++types; 
         ++args; 
        } 
        // Return number of filled results 
        return 0; 
    } 
    
    int WrapFoo(const char* types,long* args,long* results) 
    { 
        // ..function specific code.. 
        return 0; 
    } 
    
  2. Указатель на функцию обертки:

    typedef int (*TWrapper)(const char*,long*,long*); 
    
  3. Создать структуру таблицы для обернутых функций:

    struct STableItem{ 
        const char *strName; 
        TWrapper pFunc; 
    }; 
    
  4. Создать таблицу:

    STableItem table[] = { 
        {"printf", &WrapPrintf}, 
        {"foo", &WrapFoo}, 
        {NULL, NULL} 
    }; 
    
  5. Создать интерфейс для вызова любой функции из таблицы (функция поиска по имени и назовите его):

    int DynamicCall(const char *func_name,const char* types,long* args,long* results) 
    { 
        int k; 
        for(k=0;table[k].strName != NULL;++k){ 
         if(strcmp(func_name,table[k].strName) == 0){ 
          return table[k].pFunc(types,args,results); 
         } 
        } 
    
        return -1; 
    } 
    
  6. И, наконец, сделать вызов:

    long args[] = {123,'b'}; 
    long results[8];   // not nice but just for an example 
    
    int res_count = DynamicCall("printf","ic",(long*)args,(long*)results); 
    

Примечание: используйте хэш-функцию для быстрого поиска имени

+0

Не могли бы вы подробнее рассказать о хэш-функции для более быстрого поиска имени? Благодарю. – Unheilig