Форум: "Начинающим";
Текущий архив: 2009.03.29;
Скачать: [xml.tar.bz2];
ВнизБиблиотеки на С++ для Дельфи. Найти похожие ветки
← →
Drowsy (2009-02-05 01:25) [0]Можно на С++ создать библиотеку, которую можно будет в Дельфи использовать?
← →
Amoeba © (2009-02-05 01:51) [1]Если популярно, то НЕЛЬЗЯ!
← →
Германн © (2009-02-05 01:57) [2]Можно. Если есть понимание.
И даже не очень сложно.
← →
Drowsy (2009-02-05 02:58) [3]Если есть ссылка на толковую статью или примеры как это делается, буду благодарен.
← →
Amoeba © (2009-02-05 03:40) [4]
> Германн © (05.02.09 01:57) [2]
>
> Можно. Если есть понимание.
> И даже не очень сложно.
Не факт. Истина, как известно, конкретна. Смотря чего хочет автор вопроса, но есть смутное подозрение, что он имеет в виду как раз то, что невозможно (т.е. не DLL, а сишная LIB). Это и подразумевалось в моем ответе.
> Если есть ссылка на толковую статью или примеры как это
> делается, буду благодарен.
>
Что конкретно-то нужно? Все зависит от этого. Если одно - то действительно можно (проще или сложнее), если что-то другое - то на самом деле нельзя.
← →
Drowsy (2009-02-05 03:57) [5]Нашёл в инете очень полезные функции, но реализованные на С++ очень хитро. Я их загнал в C++Builder и протестировал. Есть желание понять, можно ли организовать библиотеку (или как-нибудь иначе организовать "интерфейс"), чтобы юзать эти функии в своей программе на Дельфи.
← →
Amoeba © (2009-02-05 04:38) [6]Можно, но только если под библиотекой понимается DLL. Хотя и здесь не все так однозначно (DLL не должна экспортировать или использовать в параметрах ф-ий классы C++)
← →
Drowsy (2009-02-05 05:20) [7]Нет, функции DLL ничего не будут экспортировать, кроме кода ошибки, если она произойдет.
Я в одной статье нашёл пример:
"""
Приведем исходный код динамически подключаемой библиотеки, которая называется MyDLL и содержит одну функцию MyFunction, которая просто выводит сообщение.
Сначала в заголовочном файле определяется макроконтстанта EXPORT. Использование этого ключевого слова при определении некоторой функции динамически подключаемой библиотеке позволяет сообщить компоновщику, что эта функция доступна для использования другими программами, в результате чего он заносит ее в библиотеку импорта. Кроме этого, такая функция, точно так же, как и оконная процедура, должна определяться с помощью константы CALLBACK:
MyDLL.h
#define EXPORT extern "C" __declspec (dllexport)
EXPORT int CALLBACK MyFunction(char *str);
Файл библиотеки также несколько отличается от обычных файлов на языке C для Windows. В нем вместо функции WinMain имеется функция DllMain. Эта функция используется для выполнения инициализации, о чем будет рассказано позже. Для того, чтобы библиотека осталась после ее загрузки в памяти, и можно было вызывать ее функции, необходимо, чтобы ее возвращаемым значением было TRUE:
MyDLL.c
#include <windows.h>
#include "MyDLL.h"
int WINAPI DllMain(HINSTANCE hInstance, DWORD fdReason, PVOID pvReserved)
{
return TRUE;
}
EXPORT int CALLBACK MyFunction(char *str)
{
MessageBox(NULL,str,"Function from DLL",MB_OK);
return 1;
}
После трансляции и компоновки этих файлов появляется два файла - MyDLL.dll (сама динамически подключаемая библиотека) и MyDLL.lib (ее библиотека импорта).
"""
Попробовал его скомпилировать в C++ Builder-e.
Выкидывает ошибку :
[C++ Error] DDDLLL.cpp(34): E2141 Declaration syntax error
EXPORT int CALLBACK MyFunction !!вот здесь!! (char *str)
← →
Anatoly Podgoretsky © (2009-02-05 09:14) [8]> Германн (05.02.2009 1:57:02) [2]
Нельзя, классовая модель, менеджер памяти разные.
← →
Anatoly Podgoretsky © (2009-02-05 09:15) [9]> Amoeba (05.02.2009 3:40:04) [4]
> но есть смутное подозрение, что он имеет в виду как раз то, что невозможно (т.е. не DLL, а сишная LIB).
А какая разница, если для Дельфи, а не для системы.
← →
Drowsy (2009-02-05 09:51) [10].... вроде всё же можно:
http://www.imho.ws/showthread.php?t=123792
← →
tesseract © (2009-02-05 10:30) [11]
> .... вроде всё же можно:
Конечно можно, хоть для Delphi хоть для VB. Только надо понимать как переменные в памяти храняться.
← →
Drowsy (2009-02-06 09:14) [12]проблема:
1. Есть библиотека dll скомпилированная в С++билдере
2. Если эту библиотеку использует программа написанная на С++, то всё проходит нормально.
3. А если на Дельфи, то при запуске программы ошибка возникает уже до Application.Initialize;
//---------------------------------------------------------------------------
DLLMAIN.H
//---------------------------------------------------------------------------
#if defined(_DLLMAINCPP)
# define DLL_SPEC __declspec(dllexport)
#else
# if defined(_APPMAINCPP)
# define DLL_SPEC __declspec(dllimport)
#else
# define DLL_SPEC
# endif
#endif
void DLL_SPEC Mess(char *s);
//---------------------------------------------------------------------------
DLLMAIN.CPP
//--------------------------------------------------------
#define _DLLMAINCPP
// обратите на эту строчку внимание
#include <vcl.h>
#include <windows.h>
#pragma hdrstop
#include "dllmain.h"
#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
return 1;
}
void Mess(char* p)
{
Application->MessageBox(p,"From DLL",IDOK);
}
//------------------------------------------------
//------------------------------------------------
В Дельфи:
//------------------------------------------------
unit UPAS;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
procedure Mess(var S : string); stdcall;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure Mess(var S : string); external "MYDLL.dll" name "Mess";
procedure TForm1.Button1Click(Sender: TObject);
var S : string;
begin
S := "Привет!";
Mess(S);
end;
end.
← →
tesseract © (2009-02-06 10:12) [13]про stdcall почему всегда все забывают ?
← →
tesseract © (2009-02-06 10:12) [14]Удалено модератором
← →
Anatoly Podgoretsky © (2009-02-06 10:19) [15]> Drowsy (06.02.2009 9:14:12) [12]
У тебя несовпадение типов в Mess
← →
Drowsy (2009-02-06 11:02) [16]Может быть и несовпадение.
Только, обнаружил что-то совсем странное.
Мне думалось, что компилятор хотя бы проверяет наличие библиотеки,
(не говоря уже о функциях, типах.. в библиотеке), но
он проглатывает спокойно
procedure Mess(var S : string); external "Любая фигня" name "Mess";
← →
Сергей М. © (2009-02-06 11:15) [17]
> думалось, что компилятор хотя бы проверяет наличие библиотеки
С какого перепугу-то ?
Delphi не вправе ведь запретить тебе компилить проект для исполнения на другой машине, где тобой предполагвется наличие "любой фигни")
← →
Drowsy (2009-02-06 11:26) [18]Логично, но..
А зачем тогда указывать название библиотеки, если компилтору он не нужен?
← →
Сергей М. © (2009-02-06 11:35) [19]Как это не нужен ?
Нужен !
Но не для проверки наличия, а для размещения соотв.информации в таблице импорта будущего исполняемого модуля.
Эта таблица импорта выходит на сцену в ран-тайм.
← →
Сергей М. © (2009-02-06 11:37) [20]
> Drowsy
Название DLL говорит само за себя - это динамически связываемая библиотека, т.е. вся фактическая работа с ней осуществляется в ран-тайм.
← →
Drowsy (2009-02-06 11:42) [21]Хитро.
А вновь созданную библиотеку в системе не надо регистрировать как-нибудь
(в регистрах или ещё как?)
← →
Сергей М. © (2009-02-06 11:49) [22]В данном контексте не надо.
← →
Drowsy (2009-02-06 11:55) [23]Я убрал вообще параметр:
в С++ :
void Mess(void)
{
Application->MessageBox("Messa","From DLL",IDOK);
}
в Дельфи
procedure Mess(); external "MYDLL.dll" name "Mess";
Выбрасывает ошибку:
Project raised too many consecutive exceptions: application defined exception (code xxxx) at xxxx. Process stopped.
← →
Сергей М. © (2009-02-06 12:03) [24]А где соглашения о вызове ?
← →
tesseract © (2009-02-06 12:05) [25]
> procedure Mess(); external "MYDLL.dll" name "Mess";
procedure Mess(); stdcall; external "MYDLL.dll" name "Mess";
← →
Drowsy (2009-02-06 12:07) [26]Я же указал:
procedure Mess(); stdcall;
← →
Anatoly Podgoretsky © (2009-02-06 12:07) [27]> Drowsy (06.02.2009 11:26:18) [18]
Так и необязательно, но тогда будет использоваться позднее связывание.
← →
Drowsy (2009-02-06 12:09) [28]procedure Mess(); stdcall;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure Mess(); stdcall; external "MYDLL.dll" name "Mess";
← →
Drowsy (2009-02-06 12:10) [29]Выбрасывает ошибку:
Project raised too many consecutive exceptions: application defined exception (code xxxx) at xxxx. Process stopped.
← →
Сергей М. © (2009-02-06 12:13) [30]А что показывает отладчик при пошаговой трассировке ?
← →
Drowsy (2009-02-06 12:18) [31]program PASPro;
uses
Forms,
UPAS in "UPAS.pas" {Form1};
{$R *.res}
begin // здесь останавливаю, жму F7 и вываливается: Project raised too many ...... и окно CPU
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
← →
Drowsy (2009-02-06 12:20) [32]Может какие директивы компилятору нужны или опции линка???
← →
Drowsy (2009-02-06 12:22) [33]В С++ билдере всё же идёт...
← →
Сергей М. © (2009-02-06 12:22) [34]А где текст юнита, в котором фигурирует Mess() ?
← →
Drowsy (2009-02-06 12:24) [35]Drowsy (06.02.09 09:14) [12]
← →
Drowsy (2009-02-06 12:26) [36]Только stdcall добавил, но это ничего не изменило:
procedure Mess(); stdcall; external "MYDLL.dll" name "Mess";
← →
Сергей М. © (2009-02-06 12:28) [37]Для начала собери оба проекта без использования рантайм-пакетов, потом будем обсуждать
← →
Ega23 © (2009-02-06 12:30) [38]Почему stdcall? Где он явно указан в сишной части?
ЕМНИП, там по-умолчанию cdecl используется (хотя тоже не факт).
stdcall у тебя и в приложении должно фигурировать, и в библиотеке.
← →
Drowsy (2009-02-06 12:32) [39]С готовностью.
Только я не понимаю, что значит "собери без рантаймов" -
убрать библиотеку с убогой функцией вообще?
Тогда кроме голой формы ничего не останется. :)
← →
Сергей М. © (2009-02-06 12:33) [40]
> Ega23 © (06.02.09 12:30) [38]
В дан.случае фиолетово - до собственно вызова, судя по [31], дело не додит
Страницы: 1 2 вся ветка
Форум: "Начинающим";
Текущий архив: 2009.03.29;
Скачать: [xml.tar.bz2];
Память: 0.55 MB
Время: 0.11 c