Некоторые типы вызовов в Си или кое что о DLL

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

Выражается это в том, что ты описываешь функцию, например так:

а потом пытаешься е в другом проекте задействовать, но получаешь ошибку:
«Function Test1 not found in Project1.dll»
Связано это с тем, что существуют разные «правила» именования функций в экспортной секции DLL. (Вопрос о том зачем это сделано, для меня остался загадкой. Наверняка были свои причины).
Кроме того, изначально разные компиляторы использовали схожие, но все же отличающиеся механизмы передачи параметров в/из функций.
Всем этим и управляют модификаторы типов вызова. Здесь мы будем рассматривать только те из них, которые
непосредственно затрагивают имена функций в DLL.
Создаем тестовый проект и 6 функций в нем.
без модификаторов, с модификатором __pascal и с модификатором __stdcall.
кроме того каждый вариант делаем двух видах «CPP» и «C».

Прим. __declspec(dllexport) — означает, что функция будет помещена в экспортную секцию.

Далее компилируем. Открываем экспортную секцию DLL и видим следующее (справа):
Картинка2
Функции обьявленные как «CPP» имеют в своих именах не только имя, но и полный список параметров. и модификатор.
Кроме того __pascal в варианте «CPP» перевел имя в нижний регистр.
Теперь рассмотрим функции в варианте «C»:
— к Test4 добавилось подчеркивание «_Test4»
— Test5 осталась именно такой как мы ее обьявляли
— в Тест6 все буквы стали заглавными.

Т.е. подводим итог:
— В варианте «CPP» к имени прибавляются типы параметров и модификаторы вызова.
— модификатор __pascal влияет на регистр имен (логично, паскаль же не чувствителен к регистру)
— модификатор __stdcall в варианте «С» не дает прибавить андерскор (подчеркивание).

Теперь посмотрим, как влияют эти модификаторы на способ передачи параметров.
И видим следующее:
Картинка1
Т.е у нас __stdcall и __pascal перед возвратом возвращают и стек в исходное состояние, а функции без модификаторов, возлагают эту операцию на вызывающий код. В остальном отличий вроде бы не наблюдается.

Leave a Reply

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.