Компиляция DLL с помощью gcc - PullRequest
10 голосов
/ 03 февраля 2009

оооочень я пишу скрипт-интерпретатор. И в основном, я хочу, чтобы некоторые классы и функции хранились в DLL, но я хочу, чтобы DLL искала функции в программах, которые ссылаются на нее, например,

       program                dll
----------------------------------------------------
send code to dll----->    parse code
                              |
                              v
                          code contains a function,
                          that isn't contained in the DLL
                              |
list of functions in   <------/
program
      |
      v
corresponding function,
user-defined in the
program--process the
passed argument here
      |
      \-------------->    return value sent back
                          to the parsing function

Мне было интересно, как мне скомпилировать DLL с помощью gcc? Ну, я использую порт Windows GCC. Как только я скомпилирую .dll, содержащую мои классы и функции, как мне связать его с моей программой? Как я могу использовать классы и функции в DLL? Может ли DLL вызывать функции из программы, ссылающейся на нее? Если я сделаю объект класса {...}; в DLL, тогда, когда DLL загружается программой, объект будет доступен для программы? Заранее спасибо, мне действительно нужно знать, как работать с DLL в C ++, прежде чем я смогу продолжить этот проект.

«Можете ли вы добавить более подробную информацию о том, почему вы хотите, чтобы DLL вызывала функции в основной программе?»

Я думал, что диаграмма вроде как объяснила это ... программа, использующая DLL, передает кусок кода в DLL, которая анализирует код, и если в указанном коде обнаруживаются вызовы функций, то соответствующие функции внутри DLL вызываются ... например, если я передал "a = sqrt (100)", то функция парсера DLL нашла бы вызов функции sqrt (), а внутри DLL была бы соответствующая функция sqrt (), которая вычисляла бы квадратный корень переданного ему аргумента, а затем он возьмет возвращаемое значение из этой функции и поместит его в переменную a ... как и в любую другую программу, но если соответствующий обработчик для функции sqrt () не найден в DLL (будет список поддерживаемых функций), затем она вызовет аналогичную функцию, которая будет находиться внутри программы, использующей DLL, чтобы проверить, есть ли какие-либо пользовательские функции с таким именем.

Итак, скажем, вы загрузили DLL в программу, что дает вашей программе возможность интерпретировать сценарии этого конкретного языка, программа может вызывать библиотеки DLL для обработки отдельных строк кода или передавать имена файлов сценариев для обработки ... но если вы хотите добавить в скрипт команду, которая соответствует цели вашей программы, вы можете сказать, установить логическое значение в DLL, сообщая, что вы добавляете функции к ее языку, а затем создать функцию в своем коде, которая выдаст список функции, которые вы добавляете (DLL будет вызывать ее с именем нужной ей функции; если эта функция определена пользователем и содержится в вашем коде, функция будет вызывать соответствующую функцию с аргументом, переданным ей DLL, возвращает возвращаемое значение пользовательской функции обратно в DLL, и если она не существует, она возвращает код ошибки или NULL или что-то). Я начинаю понимать, что мне придется найти другой способ, чтобы вызовы функций проходили только в одну сторону

Ответы [ 5 ]

8 голосов
/ 03 февраля 2009

Эта ссылка объясняет, как это сделать простым способом.

В виде большого изображения, когда вы создаете dll, вы создаете библиотеку, которая загружается во время выполнения. Он содержит ряд символов, которые экспортируются. Эти символы обычно являются ссылками на методы или функции плюс компилятор / компоновщик goo.

Когда вы обычно создаете статическую библиотеку, существует минимум goo, и компоновщик извлекает необходимый код и перепаковывает его для вас в свой исполняемый файл.

В dll вы на самом деле получаете два конечных продукта (три на самом деле - просто подождите): dll и библиотека-заглушка. Заглушка - это статическая библиотека, которая выглядит точно так же, как ваша обычная статическая библиотека, за исключением того, что вместо выполнения вашего кода каждая заглушка обычно является инструкцией перехода к обычной подпрограмме. Общая подпрограмма загружает вашу dll, получает адрес подпрограммы, которую вы хотите вызвать, затем исправляет оригинальную инструкцию перехода, чтобы перейти туда, поэтому, когда вы вызываете ее снова, вы попадаете в вашу dll.

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

Итак, ваши шаги таковы: создайте ваши заголовки и код, создайте dll, создайте библиотеку заглушек из заголовков / кода / некоторого списка экспортируемых функций. Код конца свяжется с библиотекой заглушки, которая загрузит DLL и исправит таблицу переходов.

Компилятор / компоновщик goo включает в себя такие вещи, как проверка того, что библиотеки времени выполнения находятся там, где они необходимы, проверка выполнения статических конструкторов, проверка регистрации статических деструкторов для последующего выполнения и т. Д. И т. Д. И т. П.

Теперь о вашей главной проблеме: как мне написать расширяемый код в dll? Существует несколько возможных способов - типичный способ - определить чистый абстрактный класс (он же интерфейс), который определяет поведение, и либо передать его в подпрограмму обработки, либо создать подпрограмму для регистрации интерфейсов для выполнения работы, а затем обработки. Подпрограмма запрашивает у регистратора объект, чтобы обработать для него часть работы.

2 голосов
/ 03 февраля 2009

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

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

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

Однако вы можете сделать часть своего API предоставлением методов из вызывающего приложения, тем самым сделав DLL полностью автономной и передавая знания в явном виде.

Как использовать классы и функции в DLL?
Включите заголовки в ваш код, когда модуль (exe или другая dll) связан, dll проверяются на полноту.

Может ли DLL вызывать функции из программы, ссылающейся на нее?
Да, но об этом нужно сказать во время выполнения.

Если я создаю объект класса {...}; в DLL, тогда, когда DLL загружается программой, объект будет доступен для программы?
Да, он будет доступен, однако есть некоторые ограничения, о которых вам необходимо знать. Например, в области управления памятью важно:

  • Свяжите все модули, совместно использующие память, с одной и той же dll для управления памятью (обычно c runtime)
  • Убедитесь, что память выделена и освобождена только в одном и том же модуле.
  • выделить в стеке

Примеры!
Вот основная идея передачи функций в dll, однако в вашем случае это может оказаться не самым полезным, поскольку вам нужно заранее знать, какие другие функции вы хотите предоставить.

// parser.h
struct functions {
  void *fred (int );
};

parse( string, functions );

// program.cpp
parse( "a = sqrt(); fred(a);", functions );

Что вам нужно, это способ регистрации функций (и их детали с помощью DLL). Большая проблема здесь - детали. Но, пропуская это, вы можете сделать что-то похожее на wxWidgets с регистрацией классов. Когда method_fred создается вашим приложением, он вызывает конструктор и регистрируется в dll посредством использования метода methodInfo. Парсер может искать methodInfo для доступных методов.

// parser.h
class method_base { };
class methodInfo {
   static void register(factory);
   static map<string,factory> m_methods;
}

// program.cpp
class method_fred : public method_base {
   static method* factory(string args);
   static methodInfo _methoinfo;
}
methodInfo method_fred::_methoinfo("fred",method_fred::factory);
0 голосов
/ 04 февраля 2009

Winrawr, прежде чем продолжить, сначала прочтите это :

Есть ли улучшения в GCC / Windows DLL / C ++ STL?

В принципе, вы можете столкнуться с проблемами при передаче строк STL вокруг ваших DLL , и у вас также могут возникнуть проблемы с исключениями, летящими через границы DLL, хотя я не сталкивался (пока). *

0 голосов
/ 03 февраля 2009

Это звучит как работа для структур данных.

Создайте структуру, содержащую ваши ключевые слова и функцию, связанную с каждым из них.

struct keyword {
    const char *keyword;
    int (*f)(int arg);
};

struct keyword keywords[max_keywords] = {
    "db_connect", &db_connect,
}

Затем напишите в вашей DLL функцию, которой вы передадите адрес этого массива:

plugin_register(keywords);

Тогда внутри DLL это может сделать:

keywords[0].f = &plugin_db_connect;

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

Взяв его на C ++, вместо этого сделайте struct классом, который содержит std :: vector или std :: map или любые другие ключевые слова и некоторые функции для управления ими.

0 голосов
/ 03 февраля 2009

Вы всегда можете загрузить dll во время выполнения с помощью load library

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...