лучше понимание экстерна “C” функции

Я просто пытаюсь далее понять функции экстерна C.

Согласно моему знанию, функция экстерна C всегда является функцией, Вы пробуете вызов из приложения, которое было уже скомпилировано. Или исполняемый файл, статическая или динамическая библиотека.

extern "C" 
{
   HRESULT CreateDevice();
   typedef HRESULT (*CREATEDEVICE)();

   HRESULT ReleaseDevice();
   typedef HRESULT (*RELEASEDEVICE)();
}

Таким образом, мой вопрос...

Мое понимание корректно??

Это должен всегда быть указатель функции C??'

Почему необходимо использовать определение типа для каждой функции??

Я предполагаю это, когда Вы используете GetProcAddress (). Вы выделяете память на том приложения подробных сведений "КУЧА" а не та, от которой Вы называете ее. Поэтому необходимо ли выпустить его от той "кучи" также??

6
задан numerical25 4 June 2010 в 03:32
поделиться

5 ответов

extern "C" имеет два значения. Во-первых, он заявляет, что символьные имена функций не "искажены" для поддержки C++. Во-вторых, он сообщает компилятору, что функция вызывается с использованием соглашения о вызове C, а не соглашения о вызове PASCAL. Разница связана с тем, когда адрес возврата заносится в стек. Использование неправильного соглашения о вызове приведет к краху вашего приложения.

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

4
ответ дан 17 December 2019 в 04:42
поделиться

Это не обязательно должен быть указатель функции. Вы можете указать объявление функции обычным образом и снабдить его префиксом extern "C", как показано в некоторых примерах Microsoft.

Если вы используете GetProcAddress(), вы не выделяете никакой памяти. Вы просто получаете адрес памяти функции внутри DLL, которая уже загружена в память (предположительно с помощью LoadLibrary()).

Даже при использовании указателей функций (например, возвращаемых GetProcAddress) вы не обязаны использовать typedef, просто без него код выглядит довольно уродливо. Также всегда трудно понять, что писать. Я думаю, это будет что-то вроде:

void (*pReleaseDevice)() = (void (__cdecl *)(void))GetProcAddress(hInstance, "ReleaseDevice");
1
ответ дан 17 December 2019 в 04:42
поделиться

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) (), хотя я считаю, что вы должны поместить его перед функцией (а не после).

0
ответ дан 17 December 2019 в 04:42
поделиться

Чтобы ответить, в порядке:

  • внешние функции "C" используются для взаимосвязи с C из C++. Их использование усваивает, что код C может вызывать функцию.Поскольку Windows API является C API, все функции являются внешними "C", чтобы гарантировать, что код C и C++ может использовать API.

  • Для того, чтобы программы C++ взаимодействовали с другими языками, включая C, в качестве соглашения, функции экспортируются с использованием extern "C". Вот почему большая часть dll-кода делает это. Однако это не является техническим требованием.

  • Так что нет, это НЕ обязательно должен быть указатель функции C.

  • Вам также не нужно использовать typedef.

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

0
ответ дан 17 December 2019 в 04:42
поделиться

Одним из важных аспектов указания связи extern "C" является то, что имена функций не искажаются, что является значением по умолчанию для имен C ++.

Чтобы функции вашей библиотеки можно было загружать с помощью GetProcAddress , вам необходимо либо добавить функцию в файл .def , либо использовать __ declspec (dllexport ) или используйте extern "C" .

0
ответ дан 17 December 2019 в 04:42
поделиться
Другие вопросы по тегам:

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