Создание системы модуля (динамическая загрузка) в C

Вы можете сделать это как:

val df = sqlContext.emptyDataFrame
if( df.eq(sqlContext.emptyDataFrame) )
    println("empty df ")
else 
    println("normal df")
36
задан Jonathan Leffler 23 December 2008 в 04:43
поделиться

7 ответов

В Linux/UNIX можно использовать POSIX dlopen / dlsym / dlerror / dlclose функции для динамичного открытия совместно использованных библиотек, и получить доступ к символам (включая функции) они обеспечивают, видят страница справочника для деталей.

32
ответ дан Robert Gamble 8 August 2019 в 15:55
поделиться

dlopen является способом пойти. Вот несколько примеров:

Загрузка плагина с dlopen:

#include <dlfcn.h>
...
int
main (const int argc, const char *argv[])
{

  char *plugin_name;
  char file_name[80];
  void *plugin;
  ...
  plugin = dlopen(file_name, RTLD_NOW);
  if (!plugin)
  {
     fatal("Cannot load %s: %s", plugin_name, dlerror ());
  }

вышеупомянутое Компиляции:

% cc  -ldl -o program program.o 

Затем принимая этот API для плагинов:

/* The functions we will find in the plugin */
typedef void (*init_f) ();
init_f init;
typedef int (*query_f) ();
query_f query;

Нахождение адреса init () в плагине:

init = dlsym(plugin, "init");
result = dlerror();
if (result)
{
   fatal("Cannot find init in %s: %s", plugin_name, result);
}
init();

С другой функцией, запрос (), который возвращает значение:

query = dlsym (plugin, "query");
result = dlerror();
if (result)
{
    fatal("Cannot find query in %s: %s", plugin_name, result);
}
printf("Result of plugin %s is %d\n", plugin_name, query ());

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

40
ответ дан idmean 8 August 2019 в 15:55
поделиться

Динамические языки как Perl делают это все время. Интерпретатор Perl записан в C, и много модулей Perl частично записаны в C. Когда те модули требуются, скомпилированные компоненты C динамично загружаются на лету. Как отмечено в другом ответе, механизм для хранения тех модулей является DLLs на окнах и совместно использованными библиотеками (.so файлы) на UNIX. Я полагаю, что призыв к загрузке общей библиотеки по UNIX является dlopen (). Можно, вероятно, найти указатели для того, как выполнить это на UNIX путем запуска с документации для того вызова. Для Windows необходимо было бы исследовать DLLs и изучить, как загрузить их динамично во времени выполнения. [Или возможно пройдите слой эмуляции UNIX Cygwin, который, вероятно, позволил бы Вам использовать те же запросы к Windows, как Вы будете на UNIX, но я не рекомендовал бы что, если Вы уже не используете и компилируете против Cygwin.]

Примечание, что это отличается от просто соединения против общей библиотеки. Если Вы будете знать заранее точно, что кодирует Вас, то будет звонить, можно создать против общей библиотеки, и сборка будет "динамично связана" с той библиотекой; без любой специальной обработки от Вас стандартные программы из библиотеки будут загружены в память только, когда и если Ваша программа на самом деле назовет их. Но Вы не можете сделать этого, если Вы планируете записать что-то способное к загрузке какого-либо произвольный объектный код, код, который Вы не можете определить теперь во время изготовления, но вместо этого ожидают, чтобы быть выбранным так или иначе во время выполнения. Для этого необходимо будет использовать dlopen () и его кузены Windows.

Вы могли бы посмотреть на способ, которым Perl или другие динамические языки делают это для наблюдения некоторых реальных примеров. Библиотекой Perl, ответственной за этот вид динамической загрузки, является DynaLoader; это имеет и Perl и компонент C, я верю. Я уверен, что другие динамические языки как Python имеют что-то подобное, на которое Вы могли бы скорее посмотреть; и у Попугая, виртуальной машины для невыпущенного Perl 6, конечно, есть механизм для того, чтобы сделать это также (или будет в будущем).

В этом отношении, Java выполняет это через свой интерфейс JNI (Java Native Interface), таким образом, Вы могли, вероятно, посмотреть на исходный код для OpenJDK, чтобы видеть, как Java выполняет это и на UNIX и на Windows.

1
ответ дан skiphoppy 8 August 2019 в 15:55
поделиться

Также можно посмотреть cpluff. Это - сменная библиотека управления по чистому c.

3
ответ дан lazyden 8 August 2019 в 15:55
поделиться

Существует подход DIY. В то время как метод (и возможность) выполнения этого варьируется от системы до системы, общее представление состоит в том, чтобы открыть файл, считать содержание файла в память, сделать, сказал исполняемый файл памяти, инициализируйте указатель функции к допустимой позиции в этой памяти, и там Вы.

, Конечно, это предполагает, что это - просто исполняемый код - довольно вряд ли. Код, вероятно, требует, чтобы данные были загружены в RAM также и может потребовать пространства для глобальных / статических переменных. Вы могли загрузить это все сами, но необходимо будет войти в исполняемый код и скорректировать все ссылки памяти в нем.

Большинство операционных систем позволяет динамическое подключение, которое делает все это для Вас.

0
ответ дан Artelius 8 August 2019 в 15:55
поделиться

Посмотрите, что на этот вопрос ответили, но думал, что другие, заинтересованные этой темой, могут ценить кросс-платформенный пример из старого основанного на плагине приложения. Пример работает над win32 или Linux и seaches для и вызывает функцию, вызванную 'конструктор' в динамично загруженном .so или .dll, определенном в аргументе файла. Пример находится в C++, но процедуры должны быть тем же для c.

//firstly the includes
#if !defined WIN32
   #include <dlfcn.h>
   #include <sys/types.h>
#else
   #include <windows.h>
#endif

//define the plugin's constructor function type named PConst
typedef tcnplugin* (*PConst)(tcnplugin*,tcnplugin*,HANDLE);

//loads a single specified tcnplugin,allmychildren[0] = null plugin
int tcnplugin::loadplugin(char *file) {
    tcnplugin *hpi;
#if defined WIN32               //Load library windows style
    HINSTANCE hplugin=LoadLibrary(file);
    if (hplugin != NULL) {
            PConst pinconstruct = (PConst)GetProcAddress(hplugin,"construct");
#else                                   //Load it nix style
    void * hplugin=dlopen(file,RTLD_NOW);
    if (hplugin != NULL) {
            PConst pinconstruct = (PConst)dlsym(hplugin,"construct");
#endif   
            if (pinconstruct != NULL) { //Try to call constructor function in dynamically loaded file, which returns a pointer to an instance of the plugin's class
                    hpi = pinconstruct(this, this, hstdout);
            } else {
                    piprintf("Cannot find constructor export in plugin!\n");
                    return 0;
            }
    } else {
            piprintf("Cannot open plugin!\n");
#if !defined WIN32
            perror(dlerror());
#endif
            return 0;
    }
    return addchild(hpi); //add pointer to plugin's class to our list of plugins
}

Мог бы также быть упомянут, что, если модуль, кто функции, которые Вы хотите вызвать, записан в C++ Ваш, должен объявить функцию с экстерном "C", таким как:

extern "C" pcparport * construct(tcnplugin *tcnptr,tcnplugin *parent) {
    return new pcparport(tcnptr,parent,"PCPARPORT",0,1);
}
8
ответ дан erisu 8 August 2019 в 15:55
поделиться

В соответствии с Windows, это - то, как я делаю это:

  • Генерируют код (в C, потому что легко найти компиляторы, и требования библиотеки минимальны)
  • , мечут икру, задание для компилирования/связывания его в DLL
  • загружаются, это с LoadLibrary
  • получает указатели функции с GetProcAddress

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

0
ответ дан Mike Dunlavey 8 August 2019 в 15:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: