DLL в .NET довольно сильно отличаются от собственных DLL. .NET DLL содержат байт-код, называемый CIL, который содержит достаточно информации для других программ, таких как компилятор csc, для разработки классов, типов, интерфейсов и т. Д., Содержащихся в нем.
Это сильно отличается от собственных DLL. Собственные библиотеки DLL содержат двоичные инструкции и в основном неструктурированные данные, и нет (в общем) способа выяснить, что означают данные - например, где-то в библиотеке DLL могут быть два байта (в шестнадцатеричном формате) 43 23
и нет никакого способа определить, будет ли программа интерпретировать их как символы C#
или как целое число 17187
, или адрес памяти, или даже инструкцию для подачи в CPU.
Итак, перейдем к вашим вопросам:
-
symbol table
- это часть метаданных для DLL; он сообщает компилятору / компоновщику, как преобразовать void myDllFunc (int bar)
в адрес в DLL. Это в основном справочная таблица. Экспорт функций из DLL - это то, как вы указываете , какие функции вы хотели бы получить в этой справочной таблице - это те функции, которые другой код сможет вызывать, потому что он сможет найти их. Помните - без другой информации невозможно определить , откуда начинается myDllFunc
.
extern C
рекомендуется из-за процесса разрешения имен и, в частности, из-за того, как C ++ обрабатывает перегрузку функций. Когда у вас есть две функции:
int square (int x);
double square (double x);
компилятору нужен какой-то способ их различения - имя «квадрат» теперь неоднозначно и не может быть разрешено в один адрес кода. C ++ обрабатывает это с помощью искажения имени - компилятор берет имя вашей функции, square
, а затем добавляет несколько магических строк, соответствующих типам в сигнатуре функции. Так, например, компилятор может видеть ваши две функции как:
int int+square+int (int x);
double dbl+square+dbl (double x);
и они больше не являются двусмысленными (реальные компиляторы не используют такую простую схему). Здесь есть две проблемы:
- Вы хотите называть эту функцию "квадратом", а не "int + square + int", и, что еще хуже,
- Различные компиляторы C ++ используют разные правила преобразования имен.
Чтобы облегчить взаимодействие, люди обычно отмечают экспортируемые ими функции с помощью extern C
, что заставляет компилятор использовать правила именования Си, в которых имя функции не искажено.
Изменить для адреса комментариев:
Объявление сигнатур функций extern C
решает проблему искажения имени, поскольку в C нет искажения имени. C может обойтись без искажения имени, потому что объявляет две функции
int square (int x);
double square (double x);
- это ошибка ; компилятор / компоновщик не должен - и не будет - обрабатывать эту неоднозначность.
Exporting a function from a DLL
- это не что иное, как добавление функции в таблицу символов. Это позволяет коду вне вашей DLL вызывать функцию, потому что теперь внешний код может искать, где запускается функция. Таким образом, функция «экспортируется», так что другие люди могут вызывать ее.