Форум: "Основная";
Текущий архив: 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