Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Как использовать dll откомпиленный для С в Delphi


Автор: Гость_Frikazoid 7.10.2003, 22:05
Доброго времени суток Господа!
Собственно сабж!
есть http://www.scancode.ru/download/10/Downl/71/
Мне надо те ф-ии в Delphi использовать!

Заранее спасибо за помощь!

Автор: Vit 7.10.2003, 23:10
ДЫк в чём проблема, все WINAPI на С написаны и импортируются без проблем...

Автор: var-alex 8.10.2003, 14:46
Импотрируешь функции из него. Только описания надо верно перевести. И обязательно установить тип вызова stdcall для импортированных функций!

Автор: Dmitry V.Abramov 8.10.2003, 15:41
Цитата
http://www.scancode.ru/download/10/Downl/71/
Мне надо те ф-ии в Delphi использовать!

Если бы это было написано на C - подошел бы любой из предложенных тебе советов.
Если бы это было писано на BCB - пришлось бы подумать, но, скорее всего, тоже удалось бы подключить.
Но то, что у тебя там лежит, писано на VC++ с активным использованием MSVCRT.DLL и наружу торчат не функции, а классы и методы. В этом случае единственным вариантом видится написание на VC "посредника", преобразующего простые cdecl вызовы из Delphi в вызовы классов этой DLL.

Автор: Dmitry V.Abramov 8.10.2003, 15:53
Цитата(Vit @ 7.10.2003, 23:10)
ДЫк в чём проблема, все WINAPI на С написаны и импортируются без проблем...

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

Автор: Гость_Frikazoid 8.10.2003, 17:11
Не могли бы вы кинуть в меня чем ни будь откомпиленным или кусок кода? Я просто с С вааще никогда не работал!

Автор: var-alex 8.10.2003, 19:13
Цитата(Dmitry @ 8.10.2003, 15:53)
Цитата(Vit @ 7.10.2003, 23:10)
ДЫк в чём проблема, все WINAPI на С написаны и импортируются без проблем...

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

Прошу извинения. Я не смотрел туда... У меня инет не резиновый, кончается иногда sad.gif

Автор: Гость_Frikazoid 9.10.2003, 19:53
Ну хоть что ни будь!
ПЛЗ!

Автор: Гость_Frikazoid 11.10.2003, 16:17
Ну, Господа, может скажите что я должен сделать?
Плиз!

Автор: Dmitry V.Abramov 11.10.2003, 19:09
Цитата(Dmitry @ 8.10.2003, 15:41)
В этом случае единственным вариантом видится написание на VC "посредника", преобразующего простые cdecl вызовы из Delphi в вызовы классов этой DLL.

Разве не помогло? Что именно не получилось?

Автор: Гость_Frikazoid 12.10.2003, 23:33
Цитата
...
Я просто с С вааще никогда не работал!

Вот это мешает!

Автор: stab 13.10.2003, 03:34
сейчас я опишу свои соображения, которые, возможно, не совсем верны и не всегда будут работать smile.gif

Эксперименты будут проводиться с:
Код

class DLLCLASSES_API CDLLClass1 {
private:
int f1, f2;
public:
CDLLClass1(int p1, int p2);

~CDLLClass1();

void Inc(int p1, int p2);

int GetF(int which);
};


CDLLClass1::CDLLClass1(int p1, int p2)
{
f1 = p1;
f2 = p2;
}

CDLLClass1::~CDLLClass1()
{
Beep(1000, f1);
}

void CDLLClass1::Inc(int p1, int p2)
{
f1 += p1;
f2 += p2;
}

int CDLLClass1::GetF(int which)
{
switch(which)
{
case 1: return f1;
case 2: return f2;
default: return -1;
}
}


после того, как скомпиляли получили dll с такими функциями:

??0CDLLClass1@@QAE@HH@Z
??1CDLLClass1@@QAE@XZ
?GetF@CDLLClass1@@QAEHH@Z
?Inc@CDLLClass1@@QAEXHH@Z
??4CDLLClass1@@QAEAAV0@ABV0@@Z

если это перевести в удобоваримую форму, то получим:

CDLLClass1::CDLLClass1(int,int)
CDLLClass1::~CDLLClass1(void)
int CDLLClass1::GetF(int)
void CDLLClass1::Inc(int,int)
class CDLLClass1 & CDLLClass1::operator=(class CDLLClass1 const &)

Последнюю процедуру мы не определяли, ее добавил компилер. Судя по всему она осуществляет копирование экземпляров класса байт к байту.

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

var
 obj: Pointer;
begin
 obj := AllocMem(8);
end;


Теперь надо вызвать конструктор. Все методы в C++, кроме методов с переменным числом параметров, используют thiscall соглашение о вызовах. thiscall -- это то же самое, что и stdcall только в ECX передается this (в Delphi-терминологии Self). Попытаемся это сделать:

Код

type
 TDLLClass1 = record
   f1, f2: Integer;
 end;
 PDLLClass1 = ^TDLLClass1;

function CDLLClass1_Create(p1: Integer; p2: Integer): Pointer; stdcall; external 'dllclasses.dll' name '??0CDLLClass1@@QAE@HH@Z';

procedure TForm1.Button1Click(Sender: TObject);
var
 obj: PDLLClass1;
begin
 obj := AllocMem(8);

 asm
   mov   ECX, [obj]
 end;

 CDLLClass1_Create(1, 2);

 ShowMessage(IntToStr(obj.f1));
end;


Теперь вызовем методы Inc и GetF:
Код

function CDLLClass1_Create(p1: Integer; p2: Integer): Pointer; stdcall; external 'dllclasses.dll' name '??0CDLLClass1@@QAE@HH@Z';
procedure CDLLClass1_Inc(p1: Integer; p2: Integer); stdcall; external 'dllclasses.dll' name '?Inc@CDLLClass1@@QAEXHH@Z';
function CDLLClass1_GetF(which: Integer): Integer; stdcall; external 'dllclasses.dll' name '?GetF@CDLLClass1@@QAEHH@Z';

procedure TForm1.Button1Click(Sender: TObject);
var
 obj: Pointer;
begin
 obj := AllocMem(8);

 asm
   mov   ECX, [obj]
 end;
 CDLLClass1_Create(1, 2);

 asm
   mov   ECX, [obj]
 end;
 CDLLClass1_Inc(1, 2);

 asm
   mov   ECX, [obj]
 end;
 ShowMessage(IntToStr(CDLLClass1_GetF(2)));
end;

Я снова объявил obj как Pointer, для того, чтобы показать ненужность знаний о внутренней структуре объекта. И на конец вызовем деструктор и освободим память.

Код

function CDLLClass1_Create(p1: Integer; p2: Integer): Pointer; stdcall; external 'dllclasses.dll' name '??0CDLLClass1@@QAE@HH@Z';
procedure CDLLClass1_Inc(p1: Integer; p2: Integer); stdcall; external 'dllclasses.dll' name '?Inc@CDLLClass1@@QAEXHH@Z';
function CDLLClass1_GetF(which: Integer): Integer; stdcall; external 'dllclasses.dll' name '?GetF@CDLLClass1@@QAEHH@Z';
procedure CDLLClass1_Destroy; stdcall; external 'dllclasses.dll' name '??1CDLLClass1@@QAE@XZ';

procedure TForm1.Button1Click(Sender: TObject);
var
 obj: Pointer;
begin
 obj := AllocMem(8);

 asm
   mov   ECX, [obj]
 end;
 CDLLClass1_Create(1, 2);

 asm
   mov   ECX, [obj]
 end;
 CDLLClass1_Inc(5000, 2);

 asm
   mov   ECX, [obj]
 end;
 ShowMessage(IntToStr(CDLLClass1_GetF(2)));

 asm
   mov   ECX, [obj]
 end;
 CDLLClass1_Destroy;

 FreeMem(obj, 8);
end;

Автор: stab 13.10.2003, 03:48
теперь о вопросе этого топика smile.gif

список функций:

??0CCipher@@QAE@XZ
??4CCipher@@QAEAAV0@ABV0@@Z
?CheckComm@CCipher@@QAEHXZ
?ClearDatabase@CCipher@@QAEHH@Z
?CloseComm@CCipher@@QAEXXZ
?Finish@CCipher@@QAEHXZ
?GetCurrentState@CCipher@@QAEHPAD@Z
?GetDataCount@CCipher@@QAEJH@Z
?GetFreeMemory@CCipher@@QAEJXZ
?GetLastError@CCipher@@QAEHPAD@Z
?GetSerialNumber@CCipher@@QAEHPAD@Z
?GetTime@CCipher@@QAEHPAD@Z
?InitComm@CCipher@@AAEHXZ
?OpenComm@CCipher@@QAEHH@Z
?OpenComm@CCipher@@QAEHHH@Z
?OpenComm@CCipher@@QAEHHHH@Z
?OpenIrDA@CCipher@@AAEHXZ
?Ping@CCipher@@QAEHXZ
?PutRecord@CCipher@@QAEHHPBD@Z
?ReadRecord@CCipher@@QAEHHPAD@Z
?SendCommand@CCipher@@AAEHPBDPAD@Z
?SendData@CCipher@@AAEHPBD@Z
?TestIrDA@CCipher@@AAEHK@Z
?TimeDly@CCipher@@AAEXXZ
?UpdateTime@CCipher@@QAEHXZ

CCipher::CCipher(void)
class CCipher & CCipher::operator=(class CCipher const &)
int CCipher::CheckComm(void)
int CCipher::ClearDatabase(int)
void CCipher::CloseComm(void)
int CCipher::Finish(void)
int CCipher::GetCurrentState(char *)
long CCipher::GetDataCount(int)
long CCipher::GetFreeMemory(void)
int CCipher::GetLastError(char *)
int CCipher::GetSerialNumber(char *)
int CCipher::GetTime(char *)
int CCipher::InitComm(void)
int CCipher::OpenComm(int)
int CCipher::OpenComm(int,int)
int CCipher::OpenComm(int,int,int)
int CCipher::OpenIrDA(void)
int CCipher::Ping(void)
int CCipher::PutRecord(int,char const *)
int CCipher::ReadRecord(int,char *)
int CCipher::SendCommand(char const *,char *)
int CCipher::SendData(char const *)
int CCipher::TestIrDA(unsigned long)
void CCipher::TimeDly(void)
int CCipher::UpdateTime(void)

проблем быть, вроде, не должно ;) самое сложное определить размер объекта, тут два варианта:

1. В VC написать sizeof(CCipher) и посмотреть чему это равно.
2. Взять заведомо достаточный объем памяти.

Вариант 1 конечно лучше.

Frikazoid, если будут проблемы с конвертацией функций в delphi -- пиши, ну и вообще если будут проблемы -- пиши smile.gif

Автор: stab 13.10.2003, 04:22
хм, sizeof(CCipher) = 1 smile.gif чего-то я не понимаю как пользоваться этой библиотекой в VC.

Код

CCipher * c = new CCipher();
c->CheckComm();

приводит к "Unhandled exception at 0x10001100 (Cipher.dll) in app.exe: 0xC0000005: Access violation reading location 0x00000020."
Обращение к любому методу приводит к эксепшенам. Похоже sizeof(CCipher) != 1 smile.gif

Автор: Dmitry V.Abramov 13.10.2003, 07:06
Цитата(cully @ 13.10.2003, 04:22)
Похоже sizeof(CCipher) != 1 :)

Хочется выказать уважение к проделанной работе, и оказать посильную помощь. Судя по коду оператора копирования
Код
; public: class CCipher & __thiscall CCipher::operator=(class CCipher const &)

??4CCipher@@QAEAAV0@ABV0@@Z proc near

arg_0           = dword ptr  8

               push    esi
               mov     esi, [esp+arg_0]
               mov     eax, ecx
               push    edi
               mov     ecx, 10h
               mov     edi, eax
               repe movsd
               pop     edi
               pop     esi
               retn    4
??4CCipher@@QAEAAV0@ABV0@@Z endp

... величина этого Cipher'a равна $10*4=64 байта.

Автор: stab 13.10.2003, 07:53
Dmitry V.Abramov, во! а я сидел думал, где бы это число нарыть smile.gif

Автор: Cashey 14.10.2003, 14:33
Простите за глупую встрячку. У меня вопросик по ходу. Можно ли в Дельфях использовать DLL'ки написанные на др. языках напрямую, не регистря их в виндах (т.е. не через OLE)?

Автор: Dmitry V.Abramov 14.10.2003, 15:51
Можно. Если вызвать в начале работы DllRegisterServer из этой DLL, а в конце DllUnregisterServer.

Автор: Cashey 14.10.2003, 15:56
Это что в самой DLL'ки прописано должно быть? Или оно вызывается перед использованием DLL

Автор: stab 14.10.2003, 17:48
перед использованием.

Автор: Cashey 15.10.2003, 10:25
А примерчик использования можно? Я вот тут одну DLL'ку, фоксовскую, использовал, регистря ее с помощью REGSVR32.EXE, и все работало, а унинсталировал ее и попробовал зделать так
Код

uses ComServ, ComObj, ComCtrls;
.......................................................................
procedure TForm4.FormCreate(Sender: TObject);
var
Registr: Variant;
begin
try
DllRegisterServer;
Registr := createoleobject('regina.regina'); //DLL называется regina.dll
except
showmessage('Невозможно установит библиотеку!');
end;
end;  

А он ругается и выдает except. Дельфийский хелп без примера, а методом проб и ошибок ковырятся не охота.

Автор: stab 15.10.2003, 10:31
Cashey, поищи на форуме, был уже такой топик.

з.ы. и ваще это уже совсем другой вопрос smile.gif модер придет -- совсем мертвый будешь smile.gif

Автор: Гость_Frikazoid 15.10.2003, 19:59
А откомпиленный длл мона? просто ставить VC не охота! ПЛЗ!

Автор: Dmitry V.Abramov 15.10.2003, 22:00
Хммм... Вообще-то мы упорно обсуждаем вот этот:

http://www.scancode.ru/download/10/Downl/71/

Автор: Гость_Frikazoid 16.10.2003, 12:18
Цитата(Dmitry @ 15.10.2003, 22:00)
Хммм... Вообще-то мы упорно обсуждаем вот этот:

http://www.scancode.ru/download/10/Downl/71/

Так я за эту же тему!
Мне нужен откомпиленный, промежуточный длл! Если можно плз!

Автор: stab 16.10.2003, 14:21
выше описан способ как без промежуточных dll можно сделать...

Автор: man2002ua 17.10.2003, 14:42
cully, смутно верится, что можно так подключить...в этой либе нет проц. DLLRegisterServer
Frikazoid, тебе достаточно будет, что в библиотеке-заглушке используется жесткий экземпляр Ciphera? (т.е. при подключении заглушки будет создаваться один класс Cipher и др. создать будет низзя) Или тебе надо предусмотреть возможность создания нескольких классов (чуть сложнее)?

Вот кстати заглушка с примером использования
http://man2002ua.hotbox.ru/ciprar.exe.sfx

Автор: stab 17.10.2003, 17:00
man2002ua, а при чем тут DLLRegisterServer? ты повнимательней почитай топик tounge.gif

Автор: man2002ua 18.10.2003, 09:02
cully, это ты про те куски асм. вставок? Способ, к-й предложил Dmitry V.Abramov вначале - IMHO самый простой и верный...

Автор: stab 18.10.2003, 09:06
man2002ua, но мы же не ищем легких путей smile.gif мы ищем эффективные smile.gif

Автор: man2002ua 18.10.2003, 09:21
Нифиговый эффективный путь smile.gif))) Раскрутить программу, чтобы узнать размер объекта smile.gif))))
Звините за оффтоп wink.gif

Автор: Dmitry V.Abramov 18.10.2003, 12:37
man2002ua Так ведь у каждого своя эффективность. Например, у меня в радиусе 30 километров нет доступного VC++ -- зато есть дебаггер. У Гость_Frikazoid, похоже, вообще ничего нет кроме интернета...

А подтема DllRegisterServer была порождена вопросом:
Цитата
Можно ли в Дельфях использовать DLL'ки написанные на др. языках напрямую, не регистря их в виндах (т.е. не через OLE)?


И шуточным ответом:
Цитата
Можно. Если вызвать в начале работы DllRegisterServer из этой DLL, а в конце DllUnregisterServer.

в конце которого было позабыто ":)".

Автор: Frikazoid 23.10.2003, 21:48
Вы себе представить не можите, что у меня под боком валяются: Pascal, Delphi, BC, VC, C++, Basik, VB, eVC, eVB (PHP, PERL wink.gif Есть ещё экзотика типа Парабилдера! Есть ещё такой фактор как здоровенная лень на изучение С++ и школа. 12 класс сдача бакалавра. работа. дети, жена :-)

Автор: Frikazoid 23.10.2003, 21:53
man2002ua Здоровенный санькс! Ща попробую!

Автор: Frikazoid 24.10.2003, 14:59
Протестил. Не работает! sad.gif

Автор: man2002ua 24.10.2003, 15:48
А что говорит? У меня выдает сообщения типа "время ожидания истекло", но мне не на чем проверить...

Автор: Frikazoid 24.10.2003, 23:25
Говорит тоже самое! Я всякие позиции попробовал, никак!
Вообще, за всё время, что я работаю с RS-232 я не имел таких проблем. Готов уже разбить этот сканер! sad.gif Я отлавливал протоколы на кассовые апараты, системы учёта посещаемости, сканеры(другие), ну нигде таких проблем небыло! По началу то я сам пытался отловить протокол и переписать его в своей проге. Не получилось.

ЗЫ На Сканкоде есть ещё и длл писаная для 1С! Подозреваю, что это оле сервер! Может её мона отпользовать, а?
Вот одним словом http://scancode.ru/catalog/153/ Всё что есть там!

Автор: man2002ua 25.10.2003, 08:49
"время истекло", значит функции работают правильно, иначе, как я понимаю - слетало бы что-либо...
А насчет оле-сервера - тут уже просто подключай его к делфи и пользуй. Если не получится - говори, попробую тоже wink.gif

Автор: Frikazoid 25.10.2003, 14:08
Да я пробовал. Не получилось! Ерорами сыпался. Правда не слишком долго пытался.

Автор: Frikazoid 25.10.2003, 14:13
Цитата(man2002ua @ 25.10.2003, 05:49)
"время истекло", значит функции работают правильно, иначе, как я понимаю - слетало бы что-либо...

А вот и нет! Он! на команды терминал отвечает какой-то пургой! То же самое происходило, когда я пытался сам всё сделать!

Автор: man2002ua 27.10.2003, 09:56
надо бы попробовать исп. эту библиотеку в программе написаной на VC++ и проверить, может ошибка в библиотеке...
Ты напиши последовательность функций, к-е надо вызывать - я сделаю пример на Си - запустишь и проверишь, если выдает тоже самое - ошибка в библиотеке или терминале smile.gif

Автор: Frikazoid 27.10.2003, 19:13
1) Инициализация ком порта
2) Ping smile.gif
Усё!

Автор: man2002ua 28.10.2003, 10:08
Вот попробуй...
http://man2002ua.hotbox.ru/CipherStub.exe

Автор: Frikazoid 28.10.2003, 22:02
Вот и . dll не работает! Скажу директору, пусть звонит к ним на контору и разбирается.

Автор: Frikazoid 28.10.2003, 22:23
Где есть хорошие доки по ком портам? А то у меня есть полный список параметров подключения стандартной проги к этому терминалу сканированной с помощью LGCOMSPY! А вот как это в код перевести не знаю!

Киньте в меня плз полным описанием по криейтфайлу со всеми пораметрами на ком порт, какие тока можгут быть! плиз!
Санькс!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)