сложная проблема C.динамический вызов функции - PullRequest
1 голос
/ 26 марта 2011

Я пишу программу на C / C ++ (, но класс c ++ не должен быть задействован ), которая разделена на 2 части.Первый - это базовая потребность в потоках и процессах.Во-вторых, пользователи могут настраивать свои собственные функции.модуль похож на то, что меня озадачивает пользовательская настройка функций.

My Need is as following: Пользователи могут создавать новый файл *. c в заданной папке, они могут писать свои собственные функции..

после того, как они произвели свои собственные функции и произвели компиляцию, я предоставляю им интерфейс, возможно, через сокет, http или команду argv.они могут вызывать функции, которые они определили ранее.они только дают мне строку типа «own_funciton», и затем я вызываю функцию, которую они определили.

The question is : how to do this? 

How can i connect the strings and the functions???

Я думаю, что, возможно, MACRO может быть решением, я прошу пользователей определить свою функцию следующим образом: Это всего лишь пример

BEGIN_FUNCTION (own_funcion)
{
   //function body
}
END_FUNCTION

HEED : когда пользователи добавляют свои новые функции, необходимо перекомпилировать всю систему.

вы можете что-то сделатьв МАКРО BEGIN_FUNCTION для сохранения строки функции и указателя функции .. Но я не знаю, как написать МАКРО конкретно .. У вас есть какие-либо советы

Ответы [ 4 ]

2 голосов
/ 26 марта 2011

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

В качестве примера, в linux вы можете посмотреть функции dlopen / dlclose / dlsym. По сути, пользователь реализует объект .so, и когда ваше приложение загружает его, он открывает файл .so с dlopen, как только библиотека загружена и пользователь вводит строку, вы можете искать конкретное имя функции с помощью dlsym и вызовите его через указатель на функцию. Как только вы закончили работу с библиотекой, вы отпускаете ее с помощью dlclose.

Здесь есть полезные библиотеки, такие как Boost.Extension, которые предоставляют многоплатформенный интерфейс для вызовов базовой ОС.

2 голосов
/ 26 марта 2011

Мм, это звучит немного похоже на архитектуру плагинов - в этом случае вам может помочь этот вопрос: Что безопасно для системы плагинов C ++? Полагаю, вам нужно написать какой-нибудь универсальный плагин, а ваш макрос предоставляет клей, который вписывается в пользовательские функции и скрывает сложные вещи.

Вы также можете взглянуть на cppunit (http://sourceforge.net/apps/mediawiki/cppunit/index.php?title=Main_Page), который, по сути, позволяет вам писать некоторые функции, оборачивать их в макросы, которые обеспечивают связь с платформой cppunit, а затем запускать их в общем тестирующем устройстве. это не кажется легкой задачей. Использование некоторого языка сценариев, такого как lua, кажется намного проще.

Обновление : Есть несколько интерпретаторов c, например Cint (http://root.cern.ch/drupal/content/cint). И, очевидно, TCC (http://bellard.org/tcc/) поддерживает вызовы стиля интерпретатора (я полагаю, это встроенная компиляция и выполнение). Я не использовал эти инструменты таким образом, но они могли бы облегчить боль вокруг проблемы «необходимости компилировать ее в динамическую DLL». Хотя я все же хотел бы услышать рациональное решение пойти по такому пути вместо использования язык сценариев, такой как Lua, который больше подходит для этих целей.

1 голос
/ 26 марта 2011

У вас есть много опций

1) Если ваши функции небольшие, вы можете создать макрос, который просто объявляет функцию и добавляет функцию к карте указателей на функции вашего типа (typedef yourfunction)

int FunctionName()
{
   //user code
}
map["FunctionName"] = FunctionName;

макрос, который делает, что нетрудно написать

, когда вы хотите выполнить, просто выберите функцию на карте и вызовите ее

2) ваши функции больше, вы должны рассмотреть систему плагинов.Dlls, которые экспортируют функцию.На «сервере» вы можете перечислить и загрузить эти библиотеки и открыть запрашиваемую функцию

3) Отличная версия, в которой используется механизм сценариев, который позволяет пользователям выполнять сценарии на сервере.Вы можете добиться этого, используя IActiveScript или один из множества доступных бесплатных скриптовых движков.

Edit :

4) Еще одна возможность, которая появиласьв моем уме.

  • Добавьте ваши .c файлы в проект dll.
  • Добавить модификатор __declspec (dllexport) к каждой функции, которую вы хотите добавить (в конечном итоге через макрос)
  • Перечислить экспортируемую функцию, например,
void EnumDllFunctions()
{
    BYTE *hMod = (BYTE*)GetModuleHandle("KERNEL32.DLL");
    IMAGE_NT_HEADERS *pnt = (IMAGE_NT_HEADERS*)&hMod[PIMAGE_DOS_HEADER(hMod)->e_lfanew];
    IMAGE_EXPORT_DIRECTORY *exp = (IMAGE_EXPORT_DIRECTORY*)&hMod[pnt->OptionalHeader.DataDirectory->VirtualAddress];
    DWORD *dwFunctions = (DWORD*)&hMod[exp->AddressOfNames];
   for (DWORD ctr = 0; ctr < exp->NumberOfNames; ctr++) 
   {
       printf("%s\n", (char*)&hMod[dwFunctions[ctr]]);
   }
0 голосов
/ 26 марта 2011

Звучит так, как будто вы ищете Интерфейс внешней функции, например libffi .

...