Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2007.01.14;
Скачать: [xml.tar.bz2];

Вниз

Расскажите как объявлять вункции из dll   Найти похожие ветки 

 
KyRo   (2006-12-19 12:32) [0]

У меня есть dll Подскажите как объявлять функции из нее в своей программе .
Что значат вот эти параметры external,stdcall и.т.д
Иодскажите что бы использовать библиотеку обязательно ли ее регить в виндовс regsvr32 ?
Заранее благодарен.


 
novill ©   (2006-12-19 12:36) [1]

справку читать пробовал?


 
Ega23 ©   (2006-12-19 12:37) [2]

external


Before you can call routines defined in a DLL, you must import them. This can be done in two ways: by declaring an external procedure or function, or by calling the Windows API directly. Whichever method you use, the routines are not linked to your application until runtime. This means that the DLL need not be present when you compile your program. It also means that there is no compile-time validation of attempts to import a routine.
Object Pascal does not support importing of variables from DLLs.

Static loading

The simplest way to import a procedure or function is to declare it using the external directive. For example,

procedure DoSomething; external "MYLIB.DLL";

If you include this declaration in a program, MYLIB.DLL is loaded once, when the program starts. Throughout execution of the program, the identifier DoSomething always refers to the same entry point in the same DLL.
Declarations of imported routines can be placed directly in the program or unit where they are called. To simplify maintenance, however, you can collect external
declarations into a separate “import unit” that also contains any constants and types required for interfacing with the DLL. (Delphi’s Windows unit is a good example.) Other modules that use the import unit can call any routines declared in it.

For more information about external declarations, see External declarations.
Dynamic loading through Windows API calls.


stdcall

When you declare a procedure or function, you can specify a calling convention using one of the directives register, pascal, cdecl, stdcall, and safecall
. For example,

function MyFunction(X, Y: Real): Real; cdecl;

...

Calling conventions determine the order in which parameters are passed to the routine. They also affect the removal of parameters from the stack, the use of registers for passing parameters, and error and exception handling. The default calling convention is register.

The register and pascal conventions pass parameters from left to right; that is, the leftmost parameter is evaluated and passed first and the rightmost parameter is evaluated and passed last. The cdecl, stdcall, and safecall conventions pass parameters from right to left.
For all conventions except cdecl, the procedure or function removes parameters from the stack upon returning. With the cdecl convention, the caller removes parameters from the stack when the call returns.

The register convention uses up to three CPU registers to pass parameters, while the other conventions pass all parameters on the stack.
The safecall convention implements COM error and exception handling.

The table below summarizes calling conventions.

Directive Parameter order Clean-up Passes parameters in registers?
register Left-to-right Routine Yes
pascal Left-to-right Routine No
cdecl Right-to-left Caller No
stdcall Right-to-left Routine No
safecall Right-to-left Routine No
The default register convention is the most efficient, since it usually avoids creation of a stack frame. (Access methods for published properties must use register.) The cdecl convention is useful when you call functions from DLLs written in C or C++, while stdcall and safecall are used for Windows API calls. The safecall convention must be used for declaring dual-interface methods. The pascal convention is maintained for backward compatibility. For more information on calling conventions, see Program control.

The directives near, far, and export refer to calling conventions in 16-bit Windows programming. They have no effect in 32-bit applications and are maintained for backward compatibility only.


 
Сергей М. ©   (2006-12-19 12:40) [3]


> что бы использовать библиотеку обязательно ли ее регить
> в виндовс regsvr32 ?


"Регить в виндовс regsvr32" нужно только те библиотеки, которые являют собой полноценные серверы автоматизации, о чем и говорит regsvr32


 
KyRo   (2006-12-19 12:51) [4]

Спасибо.
Ну вроде я все правильно делаю объявляю

unit Ps1_Unt;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, Menus, StdCtrls;

type
 TPs1 = class(TForm)
   MainMenu1: TMainMenu;
   N1: TMenuItem;
   N2: TMenuItem;
   N3: TMenuItem;
   N4: TMenuItem;
   N5: TMenuItem;
   GroupBox1: TGroupBox;
   Button1: TButton;
   Button2: TButton;
   procedure Button1Click(Sender: TObject);
   procedure Button2Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;
// а из программы ее можно вызывать так:
function myCoin_setup(mycoin_type:String):Boolean; external "MyCommPort.dll";
function myComm_setup(myport_number:LongInt;myport_setting:String):Boolean; external "MyCommPort.dll";
function myComm_status(myport_number:LongInt; myport_setting:String; mybuffer_size :LongInt;
myport_open :Boolean) :Boolean; external "MyCommPort.dll";
function myComm_Open:Boolean; external "MyCommPort.dll";
function myComm_Close:Boolean; external "MyCommPort.dll";
function myComm_poll(mycoin_number:LongInt;mycredit_value:LongInt;mytype_count:String):Bo olean; external "MyCommPort.dll";

вызываю
Bul:=myComm_Open;
и функция все время возвращает фалсе .

Эту библиотеку по документации надо регить. Я ее зарегил .

Можно ли как то проверить что библиотека нормально зарегилась в виндовсе и что программа обращается к ней ? Или если бы программа ее не находила она бы выдавала бы ошибку ?


 
Сергей М. ©   (2006-12-19 13:01) [5]

В документации наверняка есть примеры объявления и использования библ.функций.
Зачем же слепо экспериментировать ?


 
KyRo   (2006-12-19 13:08) [6]


> В документации наверняка есть примеры объявления и использования
> библ.функций.
> Зачем же слепо экспериментировать ?


Есть не спорю но там документация под Вижуал бейсик хотя сама библиотека написана на делфи.!!
И делаю то я все именно по документации и не выходит !
Вот и хочу найти в чем проблемма !
То ли я что то не так делаю , или чего то в ос не хватает или оборудование глючное что тож может быть !!


 
Ega23 ©   (2006-12-19 13:12) [7]


> И делаю то я все именно по документации и не выходит !


"Не верю!"  (с)


 
Сергей М. ©   (2006-12-19 13:12) [8]


> там документация под Вижуал бейсик


Так это ж расчудесно !)
Портировать VB-код в Делфи-код проще простого, гораздо легче чем С/СPP-код. Приводи примеры - посмотрим что там и как происходит..

И по барабану начем написана сама библиотека.


 
clickmaker ©   (2006-12-19 13:33) [9]


> Эту библиотеку по документации надо регить. Я ее зарегил
> .

а зачем регить библиотеку, если потом просто вызывать ее функции? Обычно, если регишь COM-сервер, то потом вызываешь СoCreateInstance с соотв. гуидом и вызываешь методы созданного объекта


 
Anatoly Podgoretsky ©   (2006-12-19 13:59) [10]

> Сергей М.  (19.12.2006 13:12:08)  [8]

По барабану если честная, но это видимо тот случай.


 
KyRo   (2006-12-22 11:06) [11]

И так у меня что то так не чего и не получается посмотрите может что то подскажете как выйти из положения.

По описанию библиотечных функций

Обязательно ! Перед использованием библиотеки MyCommPort.dll и исполняемого модуля PS2Comm.exe примера программы необходимо проверить наличие файлов с расширениями DLL и OCX из папки Support поставляемого ПО в системной директории WINDOWS и в случае их отсутствия разместить их там и зарегистрировать в системном реестре (см. ниже).
3.2. Состав.
DLL библиотека реализована в виде класса (class) в составе функций.
myCoin_setup(mycoin_type As String) As Boolean
myComm_setup(myport_number As Long, myport_setting As String) As Boolean
myComm_status(myport_number As Long, myport_setting As String, mybuffer_size As Long, myport_open As Boolean) As Boolean
PSCOMM_Open()As Boolean
PSCOMM_Close()As Boolean
myComm_poll(mycoin_number As Long, mycredit_value As Long, mytype_count As String) As Boolean
3.3. Функции.
myCoin_setup(mycoin_type As String). Функция устанавливает стоимость 6 каналов (монет, купюр) платежной системы. Тип функции – логическая переменная. Параметр – строковая переменная в виде перечисленных через запятую значений стоимости соответствующих каналов. По умолчанию ПО использует значение переменной, равное “5,10,25,50,100,0” и соответствующее стоимости каналов соответственно как 5, 10, 25, 50, 100 и 0.


И так я все функции объявляю вот так

type
 TPs1 = class(TForm)
   MainMenu1: TMainMenu;
   N1: TMenuItem;
   N2: TMenuItem;
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;
// а из программы ее можно вызывать так:
function myCoin_setup(mycoin_type:String):Boolean; external "MyCommPort.dll";
function myComm_setup(myport_number:LongInt;myport_setting:String):Boolean; external "MyCommPort.dll";
function myComm_status(myport_number:LongInt; myport_setting:String; mybuffer_size :LongInt;
myport_open :Boolean) :Boolean; external "MyCommPort.dll";
function myComm_Open:Boolean; external "MyCommPort.dll";
function myComm_Close:Boolean; external "MyCommPort.dll";
function myComm_poll(mycoin_number:LongInt;mycredit_value:LongInt;mytype_count:String):Bo olean; external "MyCommPort.dll";

var
 Ps1: TPs1;


После чего по документации надо сначала вызвать функцию настройки номиналов каналов , а потом функцию настройки ком порта.

Так вот когда я вызываю эту  функцию
bool:= myCoin_setup(s);
где S = "5,10,25,50,100,0" как показано в документации то
компилятор мне выдает ошибку
exception class EConvertError with message "hщ(Квадратик не знаю как написать)" is not a valid integer value  
Судя по ошибке я понимаю что функция дробит строку и переводит значение в интеджер и но меня смущает в ошибке вот эта смешеная русско английская строчка. Может оно берет и перекодирует в какую то кодировку которой у меня нет на компьютере ????

В тестовом примере на вижуал бейсике выглядит вот так
объявляют функцию
Public Declare Function myCoin_setup Lib "MyCommPort.dll" (ByVal mycoin_type As String) As Boolean
вот так  пытаются ее выполнить.
Success = myCoin_setup(ps_info.coin_type(0) & "," & ps_info.coin_type(1) & "," & ps_info.coin_type(2) & "," & ps_info.coin_type(3) & "," & ps_info.coin_type(4) & "," & ps_info.coin_type(5))

Подскажите может кто знает ?


 
clickmaker ©   (2006-12-22 11:13) [12]


> DLL библиотека реализована в виде класса (class) в составе
> функций.

что за бред? Либо класс с методами, либо набор функций. Определитесь уже, процедурный у вас подход или все же объектно-ориентированный...
подозрение вызывает также параметр типа String. Что это за стринг? В разных языках такой тип реализован по-разному.
Для универсальных ДЛЛ обычно используют PChar (char*), а для CОМ-серверов BSTR (портируется в дельфи как WideString)


 
KyRo   (2006-12-22 11:19) [13]


> что за бред? Либо класс с методами, либо набор функций.
> Определитесь уже, процедурный у вас подход или все же объектно-
> ориентированный...

Это  цитата из документации !!  Библиотека по словам поставщика написана на делфе . В ихнем тестовом примере который они постовляют они объявляют функции как обычные функции это вижуал бейсик

Option Explicit

Public Declare Function myCoin_setup Lib "MyCommPort.dll" (ByVal mycoin_type As String) As Boolean
"Public Declare Function myComm_poll Lib "D:\myWORK\VendingAnalyse\Ps-1\MyCommPort\delphi\MyCommPort.dll" (ByRef mycoin_number As Long, ByRef mycredit_value As Long, ByRef mytype_count As String, ByRef status_poll As String) As Boolean
Public Declare Function myComm_poll Lib "MyCommPort.dll" (ByRef mycoin_number As Long, ByRef mycredit_value As Long, ByRef mytype_count As String, ByRef status_poll As String) As Boolean
Public Declare Function myComm_setup Lib "MyCommPort.dll" (ByVal myport_number As Long, ByVal myport_setting As String) As Boolean
Public Declare Function myComm_status Lib "MyCommPort.dll" (ByRef myport_number As Long, ByRef myport_setting As String, ByRef myBuffer_size As Long, ByRef myport_open As Boolean) As Boolean
Public Declare Function myComm_Close Lib "MyCommPort.dll" () As Boolean
Public Declare Function myComm_Open Lib "MyCommPort.dll" () As Boolean
Public Declare Sub init Lib "MyCommPort.dll" ()
Public Declare Sub finish Lib "MyCommPort.dll" ()



 
Сергей М. ©   (2006-12-22 11:30) [14]


> KyRo   (22.12.06 11:06) [11]


В док-ции фигурирует откровенная чушь насчет классов.

Тем не менее все используемые тобой ф-ции библ-ки MyCommPort.dll, очевидно, должны иметь соглашение stdcall в их соответствующих Паскаль-декларациях.

Кр.того, формальные строковые параметры этих ф-ций следует описать не как string, а как PChar


> компилятор мне выдает ошибку
> exception class EConvertError


Компилятор не может выдать такой ошибки, это ошибка времени выполнения, а не времени компиляции.


 
KyRo   (2006-12-22 11:54) [15]


> Кр.того, формальные строковые параметры этих ф-ций следует
> описать не как string, а как PChar

stdcall вроде помогло в первой функции отработало нормально. !


> Тем не менее все используемые тобой ф-ции библ-ки MyCommPort.
> dll, очевидно, должны иметь соглашение stdcall в их соответствующих
> Паскаль-декларациях


То есть объявляюю вункции как

function myCoin_setup(mycoin_type:PChar):Boolean; stdcall; external "MyCommPort.dll";

А вызываю их так ??

myCoin_setup(PChar(str)):


 
Сергей М. ©   (2006-12-22 12:39) [16]

Да


 
KyRo   (2006-12-22 14:19) [17]

Все всем спасибо получилось.
Действительно надо было stdcall поставить и в некоторых функциях var и  const проставить для переменных, а Pchar оказался не нужным.


 
Сергей М. ©   (2006-12-22 14:48) [18]


> Pchar оказался не нужным.
>


Чего-чего ? Как это "не нужным" ?

Васик понятия не имеет ни о каких string"ах, кроме своих собственных, а ты пытаешься скормить ему дельфийскую string ...


> в некоторых функциях var и  const проставить для переменных


что за отсебячина ?

Если бы в Declare Function для некоего параметра фигурировал бы спецификатор ByRef, вот тогда бы var как раз и нужен был.

А const тут вообще ни при чем - поведение компилятора с const и без оного в части сгенерированного кода принципиально ничем не отличается.


 
Сергей М. ©   (2006-12-22 14:57) [19]

Хотя нет, вру.

Все правильно - если не указан ByVal, соответствующий дельфийский аргумент д.б. объявлен с var.

Но это не касается длинных строк.


 
KyRo   (2006-12-22 15:54) [20]

var и const я нашол в исходниках ихней программы
Public Declare Function myCoin_setup Lib "MyCommPort.dll" (ByVal mycoin_type As String) As Boolean
"Public Declare Function myComm_poll Lib "D:\myWORK\VendingAnalyse\Ps-1\MyCommPort\delphi\MyCommPort.dll" (ByRef mycoin_number As Long, ByRef mycredit_value As Long, ByRef mytype_count As String, ByRef status_poll As String) As Boolean
Public Declare Function myComm_poll Lib "MyCommPort.dll" (ByRef mycoin_number As Long, ByRef mycredit_value As Long, ByRef mytype_count As String, ByRef status_poll As String) As Boolean
Public Declare Function myComm_setup Lib "MyCommPort.dll" (ByVal myport_number As Long, ByVal myport_setting As String) As Boolean
Public Declare Function myComm_status Lib "MyCommPort.dll" (ByRef myport_number As Long, ByRef myport_setting As String, ByRef myBuffer_size As Long, ByRef myport_open As Boolean) As Boolean
Public Declare Function myComm_Close Lib "MyCommPort.dll" () As Boolean
Public Declare Function myComm_Open Lib "MyCommPort.dll" () As Boolean
Public Declare Sub init Lib "MyCommPort.dll" ()
Public Declare Sub finish Lib "MyCommPort.dll" ()


Pchar оказался не совсем не нужным но в некоторых функциях где параметр VAr и возвращается стринг, там с ним функции не хотели работать.


> Васик понятия не имеет ни о каких string"ах, кроме своих
> собственных, а ты пытаешься скормить ему дельфийскую string
> ...

Бейсик да но как мне сказали библиотека написана была на делфи ..

А документация действительно га..но !!
Половины функций и параметров вообще не описаны и если бы не их демонстративные исходники то так и бился бы головой об клавиатуру


 
Сергей М. ©   (2006-12-22 16:13) [21]


> var и const я нашол в исходниках ихней программы


Покажи, как в ихних дельфийских исходниках выглядят декларации экспортируемых функций ...


> Бейсик да но как мне сказали библиотека написана была на
> делфи


По барабану на чем она написана.

Если она писалась искл-но для использования в VB, то там должны были быть учтены особенности организации string-переменных именно в VB (еще раз - типы Delphi AnsiString и VB String несовместимы !)

В противном случае (т.е. библиотека задумывалась ими как универсальная, безотносительно сред разработки использующих ее приложений) строковые параметры были бы заданы как PChar. И если так, то соответствующие string-параметры в VB-декларациях обязаны быть предварены спецификаторами ByVal - при этом в dll передается как раз тот самый указатель на начало строкового буфера, ожидаемый соответственно дельфийским Str: PChar или его Сишным эквивалентом char *strbuf.

ByRef писать не обязательно - по умолчанию все VB-параметры вызовов передаются по ссылке, а не по значению. При этом передача VBшного string-параметра осуществляется как передача адреса внутренней управляющей структуры VB-строковых данных, а не самих строковых данных. Дельфийский же AnsiString тоже содержит внутреннюю упр.структуру, которая не совместима с упр.структурой передаваемой из VB строки, и работать с этой строкой в Делфи-коде обычным образом нельзя.


 
Сергей М. ©   (2006-12-22 16:40) [22]

Кстати, с Variant"ами та же ситуация.
Да и со всеми прочими имеющимися динамическими типами данных.
Имей ввиду.


 
KyRo   (2006-12-22 16:46) [23]


> > var и const я нашол в исходниках ихней программы
>
>
> Покажи, как в ихних дельфийских исходниках выглядят декларации
> экспортируемых функций ...

Нет ихние исходники на бейсике , а вот библиотека на делфи как они декларируют в я писал в прошлом посте.


> Если она писалась искл-но для использования в VB, то там
> должны были быть учтены особенности организации string-переменных
> именно в VB (еще раз - типы Delphi AnsiString и VB String
> несовместимы !)


А почему же у меня все начало работать ? Если я объявил вот так

function myCoin_setup(Const mycoin_type:String):Boolean; stdcall; external "MyCommPort.dll";
function myComm_setup(Const myport_number:LongInt;Const myport_setting:PChar):Boolean; stdcall; external "MyCommPort.dll";
function myComm_status(var myport_number:LongInt;var myport_setting:String; var mybuffer_size :LongInt;
var myport_open :Boolean) :Boolean; stdcall; external "MyCommPort.dll";
function myComm_Open:Boolean; stdcall; external "MyCommPort.dll";
function myComm_Close:Boolean; stdcall; external "MyCommPort.dll";
function myComm_poll(var mycoin_number:LongInt;var mycredit_value:LongInt;var mytype_count:String; var myStatus_PooL:Boolean ):Boolean; stdcall; external "MyCommPort.dll";
procedure init; stdcall; external "MyCommPort.dll";
procedure finish; stdcall; external "MyCommPort.dll";


Конечно может я и не прав поменять не сложно , мне просто интересно из за чего тогда функции у меня коректно выполняются ?


 
Сергей М. ©   (2006-12-22 16:49) [24]


> Нет ихние исходники на бейсике


Ты с дуба упал ?)

Сначала ты говоришь что


> сама библиотека написана на делфи


а теперь ты заявляешь иное.

"Как понимать тебя, Саид ?" (С)


 
KyRo   (2006-12-22 17:04) [25]

У меня есть библиотека с которой я работал и в которой находятся функции -она написана на делфи (и исходников к ней у меня нет).

И есть ихняя демонстрационная программа которая написана на бейсике.
К ней у меня есть ее исходники и документация  как они работают с библиотекой из бейсика.

В целом проблема в основном заключалась в том что документация действительно очень плохая . В ней как будто забыли упомянуть про процедуры инициализации и окончания работы с библиотекой без которых все работать отказывалось.
> procedure init; stdcall; external "MyCommPort.dll";
> procedure finish; stdcall; external "MyCommPort.dll"


Ну и конечно нужно было добавить в декларацию stdcall.
Насчет Pchar то стринг на него в дикларациях я могу поменять , но мне интересно тогда из за чего у меня выполняются функции сейчас ?


 
Сергей М. ©   (2006-12-22 17:18) [26]


> мне интересно тогда из за чего у меня выполняются функции  сейчас ?


Не знаю уж что у тебя там "выполняется", но я вижу явную несуразицу.

1.
Ихняя декларация:

Public Declare Function myCoin_setup Lib "MyCommPort.dll" (ByVal mycoin_type As String) As Boolean

Твоя декларация:

function myCoin_setup(Const mycoin_type:String):Boolean; stdcall; external "MyCommPort.dll";

С какого перепугу у тебя String, если у них ByVal ?

2.
Ихняя декларация:

Public Declare Function myComm_setup Lib "MyCommPort.dll" (ByVal myport_number As Long, ByVal myport_setting As String) As Boolean

Твоя декларация:

function myComm_setup(Const myport_number:LongInt;Const myport_setting:PChar):Boolean; stdcall; external "MyCommPort.dll";

А здесь вроде бы и правильно - твой PChar соответствует ихнему ByVal..String - но чем это отличается от 1 ? Почему там ты прописал string, а здесь PChar ?

Нет логики - нет и работоспособности программы.


 
KyRo   (2006-12-22 18:33) [27]


> С какого перепугу у тебя String, если у них ByVal ?


Почему несуразицу. Я конечно не знаю бейсика но как я понимаю

> ByVal

Это нечто похожее на Сonst в делфи что бы функция не изменяла значения переменных.
А у них

>  As String



> А здесь вроде бы и правильно - твой PChar соответствует
> ихнему ByVal..String - но чем это отличается от 1 ? Почему
> там ты прописал string, а здесь PChar ?

Прописал потому что ты говориш что так правильно ! Потому и поставил посмотреть.  
Да при такой дикларации функция работает , но если задекларировать с стрингом то тоже работает !!



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2007.01.14;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.018 c
15-1166640174
cando
2006-12-20 21:42
2007.01.14
Midi files


1-1164296458
DelphiLexx
2006-11-23 18:40
2007.01.14
Delphi 2006 и TFlowPanel, TGridPanel


2-1166430158
Любитель
2006-12-18 11:22
2007.01.14
Как можно показать n кнопок на панеле


3-1161663050
alucard
2006-10-24 08:10
2007.01.14
Как передать переменную в Rave отчёт?


15-1166984514
wl
2006-12-24 21:21
2007.01.14
шапка деда мороза





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский