Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 24.01.2012, 02:49   #1
spamer
Software Developer
Старожил
 
Аватар для spamer
 
Регистрация: 19.12.2008
Сообщений: 2,070
По умолчанию Экспорт из DLL (__declspec(dllexport) и extern "C" {}). Объясните.

Всем привет.
Есть самая обычная длл, написанная на Си:
Код:
// header
extern "C" __declspec(dllexport) void Test();
Код:
// source
#include <Windows.h>

#include "MyDLL.h"

extern "C" void __declspec(dllexport) Test()
{
	MessageBox(NULL, L"TestDLL", L"First Step", MB_OK);
}
Соответственно функция Test() вызывается из Delphi приложения вот так:
Код:
...
procedure Test(); stdcall; external 'MyDLL.dll';
...
procedure TForm1.Button1Click(Sender: TObject);
begin
  Test();
end;
Не знаю насчет правильности написанного(хотя вроде все верно), но это все отлично работает.
И вот тут нахожу такую статью на мсдн. Делаю все как там написано, в итоге код длл преобразуется в следующий:
Код:
// header
__declspec(dllexport) void Test();
Код:
// source
#include <Windows.h>

#include "MyDLL.h"

__declspec(dllexport) void Test()
{
	MessageBox(NULL, L"TestDLL", L"First Step", MB_OK);
}
И все, вызов из Delphi приложения произвести не удается - "точка входа в процедуру Test() не найдена бла-бла-бла..."
Объясните плз, почему так происходит? Ведь на мсдн дан такой пример (хотя может я чего-то не допонял при переводе)
Будь проще и люди к тебе потянутся

Последний раз редактировалось spamer; 24.01.2012 в 02:51.
spamer вне форума Ответить с цитированием
Старый 24.01.2012, 03:18   #2
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Цитата:
Сообщение от spamer Посмотреть сообщение
Код:
...
procedure Test(); stdcall; external 'MyDLL.dll';
...
procedure TForm1.Button1Click(Sender: TObject);
begin
  Test();
end;
Не знаю насчет правильности написанного(хотя вроде все верно), но это все отлично работает.
Не совсем верно. Проблемы могут появиться, когда в Test будут передаваться параметры. Дело в том, что по умолчанию в C параметры передаются по соглашению cdecl, а не stdcall, потому нужно указать это в импорте
Код:
procedure Test(); cdecl; external 'MyDLL.dll';
По поводу extern "C". В C++ функции декорируются, то бишь имя функции содержит в себе информацию о типах параметров функции. Поэтому в таблице экспорта ф-ция будет называться не Test, а Test***, где *** - какие-то символы, описывающие параметры ф-ции Test. Указывая атрибут extern "C" мы говорим, что нужно использовать не C++-ое соглашение по именованию ф-ций, а C-ое. И ф-ция будет экспортирована как просто _Test.
netrino вне форума Ответить с цитированием
Старый 24.01.2012, 04:08   #3
spamer
Software Developer
Старожил
 
Аватар для spamer
 
Регистрация: 19.12.2008
Сообщений: 2,070
По умолчанию

Насчет импорта - по идее тогда можно поменять соглашение с cdecl на stdcall в свойствах проекта длл. Следовательно в Делфи при импорте можно будет указывать stdcall, так ведь?

Насчет extern "C" - с теоретической стороны описание понятно. Но осталось неясно следующее - т.е. без extern "C" никак нельзя сделать экспорт(т.е. используя С++ согласование именования)? Так смысл тогда примера из мсдн в таком случае...
Будь проще и люди к тебе потянутся
spamer вне форума Ответить с цитированием
Старый 24.01.2012, 04:27   #4
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Цитата:
Сообщение от spamer Посмотреть сообщение
Насчет импорта - по идее тогда можно поменять соглашение с cdecl на stdcall в свойствах проекта длл. Следовательно в Делфи при импорте можно будет указывать stdcall, так ведь?
Достаточно объявить ф-цию Test, как использующую соглашение stdcall
Код:
extern "C" __declspec(dllexport) void __stdcall Test();
Цитата:
Сообщение от spamer Посмотреть сообщение
Насчет extern "C" - с теоретической стороны описание понятно. Но осталось неясно следующее - т.е. без extern "C" никак нельзя сделать экспорт(т.е. используя С++ согласование именования)? Так смысл тогда примера из мсдн в таком случае...
Импортировать можно и без extern "C", более того, если используется перегрузка ф-ции с одним именем, то только так и надо, но тогда при импорте в Delphi нужно указывать настоящее имя ф-ции (декорированное, с информацией о типах)
Пример на MSDN показывает как экспортировать функции на C++, чтобы потом их импортировать и использовать в том же C++. Внизу есть отдельная ссылка Exporting C++ Functions for Use in C-Language Executables, в которой используется extern "C".
netrino вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Вывести название соответствующей карты вида "шестерка бубен", "дама червей","туз треф" и т.п. воваава Помощь студентам 3 01.12.2011 12:50
Не удается найти точку входа " " в DLL ".dll" Linore C# (си шарп) 0 13.10.2011 10:38
при вводе на листе "магазин"- код товара появлялось "описание" товара из "склада" с "продажной ценой" aleksei78 Microsoft Office Excel 13 25.08.2009 12:04
Как "динамически" использовать "DLL" Air Общие вопросы Delphi 7 11.12.2007 21:55