Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.07.10;
Скачать: CL | DM;

Вниз

Экспорт функции из DLL   Найти похожие ветки 

 
Эдуард   (2003-06-21 23:52) [0]

Непонятная проблема возникла.

Уважаемые надеюсь на вашу помощь.

Значит есть DLL с процедурой такой:
type
PInteger = ^Integer;

procedure MyProc(P: PInteger); stdcall;
begin
{Заведомо известно, что P это указатель на тип Integer}
P^ := P^ + I;
end;

Вобщем-то хватит.

В коде программы описан тотже тип PInteger и в одной из процедур написано так:

var
P: Integer;
begin
P := 7;
MyProc(@P);
....


теперь главная проблема
если я экспортирую процедуру из DLL статически то она работает
procedure MyProc(P: PInteger); stdcall; external "mydll.dll";
а если динамически, через LoadLibrary, то указатель не передается и соответственно не возвращается.

В чем щдесь грабли???


 
DrPass ©   (2003-06-22 00:06) [1]

А в прототипе ты не забыл stdcall написать?


 
jack128 ©   (2003-06-22 01:09) [2]


> если динамически, через LoadLibrary, то указатель не передается
>

В смысле GetProcAddress возвращает NULL??

Код в студию


 
Эдуард   (2003-06-22 22:02) [3]

не много не поняли меня наверное, в параметры функции (в данном случае MyProc) передается указатель на объект типа INteger, так вот именно он и не передается :) (простите за тофтологию). А если делать не через LoadLibrary то все ОК.

2DrPAss: stdcall писал везде где надо, а точнее там везде надо. Объясните, что значит в прототипе?


 
sniknik ©   (2003-06-22 22:13) [4]

Эдуард (22.06.03 22:02)
> Объясните, что значит в прототипе?
в программе в описании.
Вобщем-то хватит. ;о)) (а лутше бы показал как оно у тебя описано/вызывается, уже бы сказали где напортачил)


 
jack128 ©   (2003-06-22 23:04) [5]


> Объясните, что значит в прототипе?

Посмотри Windows.pas. То что написано про CreateFile, например, в interface - это прототип. А то что в implementation это реализация.


 
DrPass ©   (2003-06-22 23:37) [6]


> stdcall писал везде где надо, а точнее там везде надо

Ну, чтобы не забивать голову фигней, убери его везде, где написал (и в библиотеке, и в проге). Должно заработать


 
Эдуард   (2003-06-23 12:57) [7]

Объясните мне неучу, зачем stdcall нужен?

щас код выложу


 
Skier ©   (2003-06-23 12:59) [8]

>Эдуард (23.06.03 12:57)

> Объясните мне неучу, зачем stdcall нужен?

F1 + stdcall. Делов-то...


 
Эдуард   (2003-06-23 13:24) [9]

F1 + stdcall? я читал, и есть подозрения что не понял т.к. английский все-таки наверное я в нем не силен :)

пишу код:
значит код Dll"ки

library pack;

uses
SysUtils,
Classes, Types;

type
TBytes = array [0..311] of Byte;
PBytes = ^TBytes;

procedure Shuffle(FCards: PBytes); stdcall;
var
Cards: TBytes;
i, j, rnd_pos, pack_pos: Integer;
begin
randomize;
for i:=0 to 311 do
Cards [i] := 255;
for i:=0 to 311 do
begin
rnd_pos := Random (312 - i);
j := -1;
pack_pos := -1;
repeat
Inc(pack_pos);
if Cards[pack_pos] = 255 then
Inc(j);
until rnd_pos = j;
Cards[pack_pos] := FCards^[i];
end;
FCards^ := Cards;
end;

exports Shuffle;

begin
end.


теперь вызов из программы:

короче:
var
Cards: TBytes; {описанный в DLL"ке. естесно в проге тоже тип описан}
Dll: THandle;
ShuffleProc: procedure (FCards: PBytes);
begin
@ShuffleProc := nil;
{Пытаемся загрузить библиотеку}
Dll:= LoadLibrary("MYDLL.DLL");
{Если все OK}
if Dll>= 32 then begin
{...то пытаемся получить адрес функции в библиотеке}
@ShuffleProc := GetProcAddress(Dll,"Shuffle");
{Если и здесь все OK}
if @ShuffleProc <> nil then
{...то вызываем эту функцию и показываем результат}
ShuffleProc(@Cards); {Здесь не работает}
end;
{И не забываем освободить память и выгрузить DLL}
FreeLibrary(Dll);

end;


вот собственно и все, указатель на Cards ен передается и в Dll вызывается Access Violetion (извините если не правильно написал), вообщем обращение к несуществующему участку памяти.


 
Skier ©   (2003-06-23 13:51) [10]

type
TShuffleProc = procedure (FCards: PBytes); stdcall;
var
Cards: TBytes; {описанный в DLL"ке. естесно в проге тоже тип описан}
Dll: THandle;
ShuffleProc: TShuffleProc;
begin
@ShuffleProc := nil;
{Пытаемся загрузить библиотеку}
Dll:= LoadLibrary("MYDLL.DLL");
try
{Если все OK}
if Dll>= 32 then begin
{...то пытаемся получить адрес функции в библиотеке}
@ShuffleProc := GetProcAddress(Dll,"Shuffle");
{Если и здесь все OK}
if @ShuffleProc <> nil then
{...то вызываем эту функцию и показываем результат}
ShuffleProc(@Cards); {Здесь не работает}
end;
{И не забываем освободить память и выгрузить DLL}
finally
FreeLibrary(Dll);
end; //try
end;


 
Эдуард   (2003-06-23 20:49) [11]

TShuffleProc = procedure (FCards: PBytes); stdcall; вот про это забыл написать тут, но не в этом дело. Не передается указатель на объект Cards.


 
jack128 ©   (2003-06-23 23:12) [12]


> Объясните мне неучу, зачем stdcall нужен?

Модель передачи параметров в функцию. Параметры передаются через стек или регистры процессора - это и определяет модель вызова.
stdcall - модель для апи windows
register - по умолчанию для функций Delphi
cdecl - C++
и т.д.



 
Эдуард   (2003-06-24 03:49) [13]

Так с stdcall все понятно, а вот с моей проблемой ничего не понятно, уважаемые где тут грабли то?


 
Babay ©   (2003-06-25 05:29) [14]

Я вот так сделал и все работает (Накопировал твой код и создал прогу и длл ничего почти не правил кроме того что тебе Skier указал)
ДЛЛ (полная копия)
library pack;
uses
SysUtils,
Classes, Types;

type
TBytes = array [0..311] of Byte;
PBytes = ^TBytes;

procedure Shuffle(FCards: PBytes); stdcall;
var
Cards: TBytes;
i, j, rnd_pos, pack_pos: Integer;
begin
randomize;
for i:=0 to 311 do
Cards [i] := 255;
for i:=0 to 311 do
begin
rnd_pos := Random (312 - i);
j := -1;
pack_pos := -1;
repeat
Inc(pack_pos);
if Cards[pack_pos] = 255 then
Inc(j);
until rnd_pos = j;
Cards[pack_pos] := FCards^[i];
end;
FCards^ := Cards;
end;

exports Shuffle;

begin
end.

Прога

unit Unit1;

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;

var
Form1: TForm1;

implementation

{$R *.dfm}
type
TBytes = array [0..311] of Byte;
PBytes = ^TBytes;

procedure TForm1.Button1Click(Sender: TObject);
type
TShuffleProc = procedure (FCards: PBytes); stdcall;
var
Cards: TBytes;
Dll: THandle;
ShuffleProc: TShuffleProc;
begin
@ShuffleProc := nil;
Dll:= LoadLibrary("Pack.DLL");
if Dll>= 32 then begin
@ShuffleProc := GetProcAddress(Dll,"Shuffle");
if @ShuffleProc <> nil then
ShuffleProc(@Cards); end;
FreeLibrary(Dll);
Caption:=InttoStr(cards[3]);// это просто проверка что чегото происходит
end;

end.

вот так у меня все работает сравни со соим ты гдето что то упустил наверное


 
Эдуард   (2003-06-27 17:21) [15]

полностью скопировал твой код, неработает!!!! Я только в проге добавил чтоб массив cards заполнялся 0, и он после процедуры ShuffleProc таким же и остается. Мож у меня с компом че не так?


 
Эдуард   (2003-06-27 17:36) [16]

УРА!!!!! Вродже работает, всем спасибо!!!!



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

Текущий архив: 2003.07.10;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.017 c
14-31444
gn
2003-06-21 07:41
2003.07.10
КТО ЛУЧШЕ*??????


3-31163
Step[B.M.]
2003-06-19 09:04
2003.07.10
Снова об ADO и Excel


14-31399
II
2003-06-24 13:03
2003.07.10
Кто нибуть знаком с математикой оптимизации рецептов комбикормов?


1-31329
Um
2003-06-25 06:44
2003.07.10
inherited inherited;


14-31465
Феликс
2003-06-22 18:54
2003.07.10
Епископ-гей: скандал сотрясает церковь