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

Вниз

Сишные Указатели на функции и их интерпретация в Дельфи   Найти похожие ветки 

 
AKul   (2004-01-15 09:44) [40]


> Серега (15.01.04 09:22) [38]
> Вы чего городите !!!
>
> Программы работают в разных адресных пространствах !!!!


Каждый процесс действительно имеет свое адресное пространство.
Но речь вроде бы идет не о разных процессах, а об приложении и DLL, а это одно адрессное пространство (DLL даже может быть промеппирована во все процессы.).


 
Ермак   (2004-01-15 12:01) [41]

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

Я пробовал гонять разные варианты твоей процедуры, но без Си и ДЛЛ, просто в Делфи. И что интересно, выявился некоторый плюрализьм: МЫ МОЖЕМ ПИСАТЬ И ТАК, И ТАК, А ОНО ВСЕ РАВНО РАБОТАЕТ, ХОТЯ ВРОДЕ КАК НЕ ДОЛЖНО БЫ. Процедурный тип в Делфи - довольно мутная штука с точки зрения синтаксиса.

1)
procedure Exec(P:TGetVarFunction);stdcall;
var GetVar:TGetVarFunction;
begin
GetVar:= @p; //Да, да, именно так!
//По нашей с вами логике GetVar должно бы указывать после этого
//на адрес переменной p в стеке процедуры, но...
//практика показала обратное! этот вариант работает...
//и не хуже, чем GetVar := p;
GetVar(nil,PChar("par"));
end;

2)
//А вот тут не работает, хотя по сути ничем не отличается от
//предыдущей, передаем опять указатель!
procedure Exec(P:pointer);stdcall;
var GetVar:TGetVarFunction;
begin
GetVar:= @p; //Здесь уже не прокатит, потому что p - явно заданный указатель. И GetVar покажет фиг знает куда, но почему, спрашивается, в прошлый раз работало? Только потому, что тип
передаваемой переменной был описан по другому.
GetVar(nil,PChar("par"));
end;

3)
//А вот это работает снова.
procedure Exec(P:pointer);stdcall;
var GetVar:TGetVarFunction;
begin
GetVar:= p; //Никакого преобразования типа можно не делать
GetVar(nil,PChar("par"));
end;

ВЫВОД: Попробуй переписать так или этак. Особенно 3 вариант.
Может быть, когда работаем в связке с СИ, преобразование типа дает какой-то побочный эффект.
Или первый вариант с двумя подвариантами с @ и без @.

Короче говоря, синтанализатор Делфи иногда допускает такие вот глупости. ;-( По идее, из всех возможных вариантов только один будет синтаксически правильным. Ан нет! То ли это просто недосмотр, то ли для облегчения жизни чайникам сделано... Но в хорошем языке программирования такого плюрализма быть не должно.
В Си, например.


 
афвуд   (2004-01-15 13:38) [42]

>то ли для облегчения жизни чайникам сделано...

Мне кажется именно для этого и сделано.
В общем могу сказать только одно:
Переменная GetVar не меняется когда мы делаем
GetVar:= p;
Причём не меняется при любых вариациях(т.е. GetVar:=@p, @GetVar:= p;(как бы глупо не выглядели некторые конструкции я пробовал всё) и т.д.) И чего делать я пока не знаю...


 
Digitman   (2004-01-15 14:15) [43]


> афвуд © (15.01.04 13:38) [42]


а на кой шут вообще нужна тебе эта лок.переменная ?

вызывай напрямую :

TGetVarFunction = function(ptr:Pointer;VarName:PChar):Variant;stdcall;

procedure Exec(P:pointer); stdcall;
begin
TGetVarFunction(p)(nil, "par");
end;

если не уверен, что фактически переданный Р-параметр есть корректный адрес в корректном модуле, то можешь перед вызовом проверить :

procedure Exec(P:pointer); stdcall;
begin
if FindHInstance(P) <> 0 then
TGetVarFunction(p)(nil, "par")
else
ShowMessage("Переданный указатель " + IntToHex(P, 8) + " есть черт те что и черт те где находящееся, но только не адрес, принадлежащий одному из загруженных модулей текущего процесса");
end;


 
Digitman   (2004-01-15 14:20) [44]


> афвуд © (15.01.04 13:38) [42]


в догонку..

коль речь у тебя идет о стыке BCB и Делфи, то надеюсь, что передаешь ты действительно указатель на процедуру , а не на процедурный метод объекта ... хотя на упомянутую проблему это повлиять непосредственно не может ... "грабли" стукнут уже при выполнении того метода. адрес которого был передан


 
Ермак   (2004-01-15 16:34) [45]

>В общем могу сказать только одно:
>Переменная GetVar не меняется когда мы делаем
>GetVar:= p;
>Причём не меняется при любых вариациях(т.е. GetVar:=@p, >@GetVar:= p;(как бы глупо не выглядели некторые конструкции я >пробовал всё) и т.д.) И чего делать я пока не знаю...

Типа, как не меняется? Присваивания НЕ ПРОИСХОДИТ?!!
Бред собачий какой-то... Первый раз такое вижу...

Попробуй не присваиванием, а вот так:
Move(p, GetVar, SizeOf(pointer))

Или асеммблерную вставку с mov. Правда, точный синтаксис подзабыл.

asm
mov eax, p
mov GetVar, eax
end;

или вообще че нибудь по типу

asm
mov eax, p
call eax
end;

Пардон, если ошибся в Асме...


 
Ермак   (2004-01-15 16:45) [46]

А еще может быть...
Может из-за stdcall?
Там же в стеке в другом порядке параметры загоняются...
А при присваивании какая-то фигня возникает из-за этого?
Может такое быть?
По-моему нет, но все же...

Попробуй в проге на С не писать __stacall, т.е. оставить процедуру с сишным стандартом, а вот в Делфях вместо
stdcall написать cdecl - это значит, будет использоваться сишный стандарт (C DECLaration).

И еще, если мне память не изменяет, стандарт stdcall, который юзает ВИнда, предусматривает еще дополнительный тип CALLBACK,
с которым нужно компилить процедуры, кторые будут вот так вызываться, через указатель между прогой и ДЛЛ...
В Делфи это не юзается, там даже слова такого нет - callback,
а вот в C++ всегда это слово добавляется перед коллбэчными :) процедурами. Вспомни ВИНАПИ функции, где мы им какую-нибудь процедуру свою передаем - там всегда тип процедуры CALLBACK.
ЧЕстно говоря, я в Си это никогда не писал, поэтому не скажу точно, но надо что-то типа
void __stdcall CALLBACK proc()

или
void WINAPI CALLBACK proc()

Еще фишка... Я в Си не мастер, но знаю точно, что эквивалент Дельфяцкому stdcall в Си - это именно WINAPI. Может, stadcall в Си - это не то же самое?


 
AKul   (2004-01-15 16:45) [47]


> афвуд © (15.01.04 13:38) [42]

> Переменная GetVar не меняется когда мы делаем
> GetVar:= p;
> Причём не меняется при любых вариациях(т.е. GetVar:=@p,
> @GetVar:= p;(как бы глупо не выглядели некторые конструкции
> я пробовал всё) и т.д.) И чего делать я пока не знаю...


Быть такого не может! Разве что оптимизатор посчитал, что переменная GetVar не используется после присваивания, и выкинул присваивание.

В любом случае, посмотри во что компилируется строка GetVar:=P (в окне CPUView). Можешь прислать сюда этот кусок ассемблерного кода сюда.


 
Striker   (2004-01-16 20:00) [48]


> И еще, если мне память не изменяет, стандарт stdcall, который
> юзает ВИнда, предусматривает еще дополнительный тип CALLBACK,
> с которым нужно компилить процедуры, кторые будут вот так
> вызываться, через указатель между прогой и ДЛЛ...


Если мне не изменяет мой склероз, то в C/C++ CALLBACK, равно как и WINAPI, эквивалентны дерективе __stdcall. Это, по идее, макрос препроцессора, что-то типа #define CALLBACK __stdcall. Так что разницы вроде быть не должно.


 
афвуд   (2004-01-19 11:21) [49]

Народ, ошибка видать где-то совсем в непонятном месте. Просто написал другую дельфийскую библиотеку и там ВСЁ ЭТО РАБОТАЕТ. Всем спасибо за советы. Я думаю этот баг я как-нибудь выловлю.



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

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

Наверх




Память: 0.55 MB
Время: 0.009 c
1-93552
Mihey
2004-01-17 19:39
2004.01.29
EOutOfResources - нехватает хэндлов


7-93728
blackman
2003-11-13 13:25
2004.01.29
Необходимо вынимать вложение из банка сообщения OutlookExpress


1-93571
Term
2004-01-13 16:14
2004.01.29
Нужна документация по написанию интерпретаторов


14-93626
Knight
2004-01-08 15:43
2004.01.29
Почему у Adobe вечно проблемы с русским?


1-93565
MakNik
2004-01-15 12:23
2004.01.29
TEdit





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский