Я просто пытаюсь далее понять функции экстерна C.
Согласно моему знанию, функция экстерна C всегда является функцией, Вы пробуете вызов из приложения, которое было уже скомпилировано. Или исполняемый файл, статическая или динамическая библиотека.
extern "C"
{
HRESULT CreateDevice();
typedef HRESULT (*CREATEDEVICE)();
HRESULT ReleaseDevice();
typedef HRESULT (*RELEASEDEVICE)();
}
Таким образом, мой вопрос...
Мое понимание корректно??
Это должен всегда быть указатель функции C??'
Почему необходимо использовать определение типа для каждой функции??
Я предполагаю это, когда Вы используете GetProcAddress (). Вы выделяете память на том приложения подробных сведений "КУЧА" а не та, от которой Вы называете ее. Поэтому необходимо ли выпустить его от той "кучи" также??
extern "C" имеет два значения. Во-первых, он заявляет, что символьные имена функций не "искажены" для поддержки C++. Во-вторых, он сообщает компилятору, что функция вызывается с использованием соглашения о вызове C, а не соглашения о вызове PASCAL. Разница связана с тем, когда адрес возврата заносится в стек. Использование неправильного соглашения о вызове приведет к краху вашего приложения.
Это объявление предназначено для компилятора, а не для компоновщика. Поэтому функция extern C может существовать в ваших собственных модулях или в двоичной библиотеке: источник фактических байтов для реализации функции определяется компоновщиком. Если сигнатура функции объявлена как обычная функция C++, а не extern C, компилятор исказит символическое имя, чтобы закодировать информацию о типе из сигнатуры функции. Это сделает ее несовместимой с объектным кодом, сгенерированным другими компиляторами C++. Поэтому создание функции extern C позволяет обмениваться кодом между компиляторами в двоичной форме. Обратите внимание, что таким образом нельзя раскрывать функции-члены, только функции старого стиля C.
Это не обязательно должен быть указатель функции. Вы можете указать объявление функции обычным образом и снабдить его префиксом extern "C"
, как показано в некоторых примерах Microsoft.
Если вы используете GetProcAddress()
, вы не выделяете никакой памяти. Вы просто получаете адрес памяти функции внутри DLL, которая уже загружена в память (предположительно с помощью LoadLibrary()
).
Даже при использовании указателей функций (например, возвращаемых GetProcAddress) вы не обязаны использовать typedef
, просто без него код выглядит довольно уродливо. Также всегда трудно понять, что писать. Я думаю, это будет что-то вроде:
void (*pReleaseDevice)() = (void (__cdecl *)(void))GetProcAddress(hInstance, "ReleaseDevice");
extern "C" {} - это соглашение C ++, объявляющее включенные функции функциями C, а не функциями C ++. C ++ имеет несколько иное соглашение об именах, которое конфликтует с C. Если у вас есть библиотека, написанная на C, и вы хотите использовать ее в программе на C ++, вы должны использовать extern «C» {}, чтобы компилятор знал, что это функции C. Если библиотека была написана на C ++, я считаю, что extern "C" {} вызовет ошибку.
Обратите внимание, что extern имеет несколько значений - этот конкретный случай является соглашением C ++ и не связан с различным использованием extern. Например,
extern int count;
имеет совершенно другое значение, чем extern "C" {}.
Определение типа не связано с проблемой extern "C" {}. typedefs позволяет создавать более понятные псевдонимы для общих типов. Например, объявление структур часто бывает многословным. Я могу использовать typedef, чтобы сократить его:
struct mystruct {int a; int b};
typedef struct mystruct returncode;
// I can now declare a variable as type 'returncode'
returncode a;
Таким образом, в вашем примере HRESULT на самом деле является псевдонимом для (* CREATEDEVICE) (), хотя я считаю, что вы должны поместить его перед функцией (а не после).
Чтобы ответить, в порядке:
внешние функции "C" используются для взаимосвязи с C из C++. Их использование усваивает, что код C может вызывать функцию.Поскольку Windows API является C API, все функции являются внешними "C", чтобы гарантировать, что код C и C++ может использовать API.
Для того, чтобы программы C++ взаимодействовали с другими языками, включая C, в качестве соглашения, функции экспортируются с использованием extern "C". Вот почему большая часть dll-кода делает это. Однако это не является техническим требованием.
Так что нет, это НЕ обязательно должен быть указатель функции C.
Приведенный пример кода взят из файла заголовка, в который дважды публикуется экспорт библиотеки DLL — один раз в виде набора внешних методов "C", которые экспортируются таким образом, чтобы библиотека DLL могла быть статически связана. другой — как набор типов указателей функций, так что библиотека DLL может быть динамически загружена, и типы указателей функций, используемые с GetProcAddress.
Одним из важных аспектов указания связи extern "C"
является то, что имена функций не искажаются, что является значением по умолчанию для имен C ++.
Чтобы функции вашей библиотеки можно было загружать с помощью GetProcAddress
, вам необходимо либо добавить функцию в файл .def , либо использовать __ declspec (dllexport )
или используйте extern "C"
.