Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 1 марта!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

БОЛЬШОЙ FAQ ПО DELPHI



Вызов Delphi DLL из MS Visual C++

Without C we'd have BASI, PASAL, OBOL ;-)

Во-первых, Вам необходимо объявить все экспортируемые в Delphi DLL функции с ключевыми словами export; stdcall;

Во-вторых, файл заголовка VC++ должен объявить все функции как тип __declspec(dllexport) __stdcall (применяйте двойное подчеркивание в секции объявления прототипа функции extern "C" { ... }. (вместо этого можно также использовать __declspec(dllimport)...). Для примера:


 extern "C" {
 int  __declspec(dllexport)     __stdcall plusone(int); }
 

В-третьих, в VC++ компилятор настраивается на "украшающее" имена функций __stcall, так что Ваша Delphi DLL соответственно должна экспортировать эти функции. Для этого необходимо модифицировать файл Delphi 2.0 .DPR для Вашего DLL, модифицируя имена всех функций, прописанных в разделе экспорта. Для примера, если Вы экспортируете функцию function plusone (intval : Integer), Вам необходимо включить следующую строку в раздел экспорта .DPR-файла:


 plusone name 'plusone@4'
 

Число, следующее за символом @, является общей длиной в байтах всех функциональных аргументов. Самый простой путь для обнаружения неправильных значений - попытаться слинковать Вашу VC++ программу и посмотреть на наличие возможной ошибки компоновщика "unresolved external".

И, наконец, Вы можете легко создать библиотеку импорта, используя утилиту LIB из поставки VC++. Для этого необходимо вручную (!!) создать .DEF-файл для Вашей DLL с секцией экспорта, перечисляющей имена и/или порядковые номера всех экспортируемых DLL функций. Формат .DEF-файла очень прост:


 library MYLIB
 description 'Моя собственная DLL'
 exports
 
 plusone@4
 

Затем запускаете LIB из командной строки DOS/Win95, и в качестве параметра подставляете имя .DEF-файла. Например, LIB /DEF:MYDLL.DEF. Наконец, через диалог Build|Settings|Linker Вы информируете VC++ о полученном .LIB-файле.

Вот пример кода:

*******MYDLLMU.PAS


 unit MyDLLMU;
 
 interface
 
 function plusone(val : Integer) : Integer; export; stdcall;
 procedure ChangeString(AString : PChar); export; stdcall;
 
 implementation
 
 uses
 
 Dialogs,
 SysUtils;
 
 function plusone(val : Integer) : Integer;
 begin
 
 Result := val + 1;
 end;
 
 procedure ChangeString(AString : PChar);
 begin
 
 if AString = 'Здравствуй' then
 StrPCopy(AString, 'Мир');
 end;
 
 end.
 

***********MYDLL.DPR


 library mydll;
 
 { Существенное замечание об управлении памятью в DLL: Если DLL экспортирует функции со
 
 строковыми параметрами или возвращающие строковые значения, модуль ShareMem надо
 указывать в разделе Uses библиотеки и проекта первым. Это касается любых строк,
 передаваемых как в DLL, так и из нее, даже если они размещаются внутри записей или
 объектов. Модуль ShareMem служит интерфейсом менеджера разделяемой памяти
 DELPHIMM.DLL, который должен разворачиваться одновременно с данной DLL. Чтобы избежать
 применения DELPHIMM.DLL, строковую информацию можно передавать с помощью параметров
 типа PChar или ShortString. }
 
 uses
 
 SysUtils,
 Classes,
 MyDLLMU in 'MyDLLMU.pas';
 
 exports
 
 plusone name 'plusone@4',
 ChangeString name 'ChangeString@4';
 
 begin
 end.
 

*************** MYDLL.DEF
; -----------------------------------------------------------------
; Имя файла: MYDLL.DEF
; -----------------------------------------------------------------


 LIBRARY  MYDLL
 
 DESCRIPTION  'Тестовая Delphi DLL, статическая загрузка в VC++ приложение'
 
 EXPORTS
 
 plusone@4
 

************** DLLTSTADlg.H


 // DLLTSTADlg.h : заголовочный файл
 //
 #define USELIB
 #ifdef USELIB
 extern "C" {
 
 int __declspec(dllimport) __stdcall plusone(int);
 }
 #endif //USELIB
 /////////////////////////////////////////////////////////////////////////////
 // Диалог CDLLTSTADlg
 
 class CDLLTSTADlg : public CDialog
 {
 // Создание public:
 
 CDLLTSTADlg(CWnd* pParent = NULL);      // стандартный конструктор
 ~CDLLTSTADlg();
 
 // Данные диалога
 
 //{{AFX_DATA(CDLLTSTADlg)
 enum { IDD = IDD_DLLTSTA_DIALOG };
 CString m_sVal;
 CString m_sStr;
 //}}AFX_DATA
 
 
 // Перекрытая виртуальная функция, сгенерированная ClassWizard
 //{{AFX_VIRTUAL(CDLLTSTADlg)
 protected:
 virtual void DoDataExchange(CDataExchange* pDX);        // Поддержка DDX/DDV
 //}}AFX_VIRTUAL
 
 // Реализация
 protected:
 
 #ifndef USELIB
 
 HINSTANCE hMyDLL;
 FARPROC lpfnplusone;
 typedef int (*pIIFUNC)(int);
 pIIFUNC plusone;
 #endif //USELIB
 
 
 HICON m_hIcon;
 
 
 // Карта функций генераций сообщений
 //{{AFX_MSG(CDLLTSTADlg)
 virtual BOOL OnInitDialog();
 afx_msg void OnPaint();
 afx_msg HCURSOR OnQueryDragIcon();
 afx_msg void OnBtnplusone();
 afx_msg void OnBtnplusoneClick();
 afx_msg void OnBtndostringClick();
 //}}AFX_MSG
 DECLARE_MESSAGE_MAP()
 };
 

************ DLLTSTADlg.CPP


 // DLLTSTADlg.cpp : файл реализации
 //
 
 #include "stdafx.h"
 #include "DLLTSTA.h"
 #include "DLLTSTADlg.h"
 
 #ifdef _DEBUG
 #define new DEBUG_NEW
 #undef THIS_FILE
 static char THIS_FILE[] = __FILE__;
 #endif
 
 extern CDLLTSTAApp theApp;
 
 /////////////////////////////////////////////////////////////////////////////
 // Диалог CDLLTSTADlg
 
 CDLLTSTADlg::CDLLTSTADlg(CWnd* pParent /*=NULL*/)
 
 : CDialog(CDLLTSTADlg::IDD, pParent)
 {
 
 //{{AFX_DATA_INIT(CDLLTSTADlg)
 m_sVal = _T("1");
 m_sStr = _T("Hello");
 //}}AFX_DATA_INIT
 // Имейте в виду, что в Win32 LoadIcon не требует последующего DestroyIcon
 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
 
 #ifndef USELIB
 
 hMyDLL = LoadLibrary("C:\\delpwork\\MYDLL.DLL");
 if(hMyDLL == NULL)
 PostQuitMessage(1);
 lpfnplusone = GetProcAddress(HMODULE(hMyDLL), "_plusone");
 if(lpfnplusone == NULL)
 PostQuitMessage(2);
 plusone = pIIFUNC(lpfnplusone);
 #endif //USELIB
 
 }
 
 CDLLTSTADlg::~CDLLTSTADlg()
 {
 #ifndef USELIB
 
 if (hMyDLL != NULL)
 FreeLibrary(hMyDLL);
 #endif //USELIB
 }
 
 void CDLLTSTADlg::DoDataExchange(CDataExchange* pDX)
 {
 
 CDialog::DoDataExchange(pDX);
 //{{AFX_DATA_MAP(CDLLTSTADlg)
 DDX_Text(pDX, IDC_LBLINT, m_sVal);
 DDX_Text(pDX, IDC_LBLSTRING, m_sStr);
 //}}AFX_DATA_MAP
 }
 
 BEGIN_MESSAGE_MAP(CDLLTSTADlg, CDialog)
 
 //{{AFX_MSG_MAP(CDLLTSTADlg)
 ON_WM_PAINT()
 ON_WM_QUERYDRAGICON()
 ON_BN_CLICKED(IDC_BTNPLUSONE, OnBtnplusoneClick)
 ON_BN_CLICKED(IDC_BTNDOSTRING, OnBtndostringClick)
 //}}AFX_MSG_MAP
 END_MESSAGE_MAP()
 
 /////////////////////////////////////////////////////////////////////////////
 // Дескрипторы сообщений CDLLTSTADlg
 
 BOOL CDLLTSTADlg::OnInitDialog()
 {
 
 CDialog::OnInitDialog();
 
 
 // Устанавливаем иконку для данного диалога.  В случае, когда главное
 // окно программы не является диалогом, это происходит автоматически
 SetIcon(m_hIcon, TRUE);                 // Устанавливаем большую иконку
 SetIcon(m_hIcon, FALSE);                // Устанавливаем маленькую иконку
 
 
 // TODO: Здесь добавляем дополнительную инициализацию
 
 
 return TRUE;  // возвращает TRUE в случае отсутствия фокуса у диалога
 }
 
 // Если Вы добавляете в диалог кнопку минимизации, для создания иконки Вам
 //  необходим код, приведенный ниже. Для MFC-приложений используйте
 //  document/view model для автоматического создания скелета кода.
 
 void CDLLTSTADlg::OnPaint()
 {
 
 if (IsIconic())
 {
 CPaintDC dc(this); // контекст устройства для рисования
 
 
 SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
 
 
 // Центр иконки в области клиента
 int cxIcon = GetSystemMetrics(SM_CXICON);
 int cyIcon = GetSystemMetrics(SM_CYICON);
 CRect rect;
 GetClientRect(&rect);
 int x = (rect.Width() - cxIcon + 1) / 2;
 int y = (rect.Height() - cyIcon + 1) / 2;
 
 
 // Рисование иконки
 dc.DrawIcon(x, y, m_hIcon);
 }
 else
 {
 CDialog::OnPaint();
 }
 }
 
 // Система вызывает данный код для получения курсора, выводимого если
 //  пользователь пытается перетащить свернутое окно.
 HCURSOR CDLLTSTADlg::OnQueryDragIcon()
 {
 
 return (HCURSOR) m_hIcon;
 }
 
 void CDLLTSTADlg::OnBtnplusoneClick()
 {
 
 int iTemp;
 char sTemp[10];
 
 
 
 iTemp = atoi(m_sVal);
 iTemp = plusone(iTemp);
 m_sVal = itoa(iTemp, sTemp, 10);
 UpdateData(FALSE);
 }
 
 void CDLLTSTADlg::OnBtndostringClick()
 {
 
 UpdateData(FALSE);
 }
 




<< ВЕРНУТЬСЯ В ОГЛАВЛЕНИЕ



Материалы находятся на сайте https://exelab.ru/pro/



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS