Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 3 621

/ вопрос открыт /

Здравствуйте, уважаемые эксперты!
Моя проблема заключается вот в чём:
Есть dll с унифицированной функцией function ObeyCommands(Arg: string): pointer;
В ней, в зависимости от того какой Arg выполняются разные действия и она выдаёт поинтеры на разные значения (типы данных у значений тоже разные)
В ней код:

if Arg='GetWanIP' then
  begin
    Result:=PChar(SomeFuncThatReturnStr);
  end;
SomeFuncThatReturnStr - некоторая функция возвращающая строку - тип string (получение айпишника на самом деле)

А ещё есть программа, где эта либа подгружается и выполняется команда вида
lbIP.Caption:=string(ObeyCommands('GetWanIP'));
и значение Caption при этом не меняется, тоесть было оно, скажем, 255.255.255.255 а должно стать 1.2.3.4 (потому что искомый айпи такой), но оно остаётся 255.255.255.255

Как сделать чтобы значение корректно сменялось? Уже весь мозг себе сломал :( Заранее спасибо!

MOZGIII Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: MOZGIII (статус: Посетитель)
Вопрос отправлен: 5 января 2010, 21:01
Состояние вопроса: открыт, ответов: 0.


Мини-форум вопроса

Всего сообщений: 10; последнее сообщение — 6 января 2010, 21:30; участников в обсуждении: 3.
Вадим К

Вадим К (статус: Академик), 5 января 2010, 21:25 [#1]:

"не поменяться" оно может в двух случаях.
- эта строка кода просто не выполняется (например чуточку выше есть if)
- новое значение не отличается от старого. И ничего, что Вы уверенны, что оно должно быть другим. Только логированние подскажет правильный ответ.

Поэтому
- делаем логирование в dll и убеждаемся, что там то, что надо (в простейшем случае можно просто делать запись в файл)
- убеждаемся, что эта строка кода исполняется (ставим точку останова).
- проверяем, что в проект добавлено ShareMem:)
Галочка "подтверждения прочтения" - вселенское зло.
MOZGIII

MOZGIII (статус: Посетитель), 6 января 2010, 02:34 [#2]:

Тут не бошлось без магии: во-первых строчка кода точно выполняется,а во вторых если рядом поставить ShowMessage(string(ObeyCommands('GetWanIP'))) то он выводит нужное значение...
И даже если использовать
tmpvar:=string(ObeyCommands('GetWanIP'));
ShowMessage(tmpvar);
lbTxt.Caption:=tmpvar;
.. значения разные - лейбл не меняется! И ещё, эта конструкция работает и без ShareMem-ов, но у меня используется FastShareMem;
Эх, если бы проблема была так проста... я думаю дело с поинтерами (путаница)
Больше вообще идей нет.
И ещё, там однопотоковый код, мьютексы точно ненужны...
MOZGIII

MOZGIII (статус: Посетитель), 6 января 2010, 02:36 [#3]:

Помогите разобраться, ато придётся много капать асмы и работать дебаггером :)
Вадим К

Вадим К (статус: Академик), 6 января 2010, 12:46 [#4]:

Асм тут точно не надо, он не панацея. А вот отладчик - думаю стоит.

Цитата (MOZGIII):

И ещё, эта конструкция работает и без ShareMem-ов

Ну да, работает, чуть код усложниться и наступит ад отладки.
Но раз есть FastShareMem, но все хорошо. Это его заменитель.
"путаницы поинтеров" я тут точно не вижу. На С много программировали?
Текст может не меняться по нескольким причинам.
Например, есть где то таймер, который эту метку постоянно инициализирует старым значением.
Второй вариант - строка возвращается не совсем корректной. Попробуйте выводить не в метку, а например в memo, edit и так далее.
Галочка "подтверждения прочтения" - вселенское зло.
vlsavkin

vlsavkin (статус: 2-ой класс), 6 января 2010, 13:02 [#5]:

Есть подозрение, что все гораздо проще, Вы точно тому label'у передаете строковое значение?
А то lbIP.Caption:=string(ObeyCommands('GetWanIP')); и lbTxt.Caption:=tmpvar; перепутать не могли имя?
MOZGIII

MOZGIII (статус: Посетитель), 6 января 2010, 16:49 [#6]:

Имя я не путал...
На С совсем чуть-чуть, с поитерами на нём не работал
>Например, есть где то таймер, который эту метку постоянно инициализирует старым значением.
Я уже говорил на эту тему - всмысле мютексы ненужны :) Хотя там есть таймер, он значения не имеет

Кое что интересное я нашёл:
ObeyCommands() переделал на выдачу конструкции типа рекорд
record
  Value: Pointer;
  Error: Integer;
end;

это в with ObeyCommands('GetWanIP') do
if fmMain.lbInfoWANIP.Caption<>string(Value) then ShowMessage('Не совпадают! '+fmMain.lbInfoWANIP.Caption+' -
'+string(Value))
              else ShowMessage('Cовпадают! '+fmMain.lbInfoWANIP.Caption+' - '+string(Value))
Всегда пишет Совпадают! 255.255.255.255 - 255.255.255.255

Попробовал присвоить кепшену формы - кепшн не изменился...

Кажется надо залесть в опции компилятора, так как путанница всёже есть ;)
MOZGIII

MOZGIII (статус: Посетитель), 6 января 2010, 16:54 [#7]:

Лазил в компиляторе - не помогло
MOZGIII

MOZGIII (статус: Посетитель), 6 января 2010, 17:03 [#8]:

И ещё: если сделать присваивание не string(Value) а string(PChar(Value)), то присваивание происходит, но присваисвается строка без поледнего символа, например "1.2.3." вместо "1.2.3.4"
Вадим К

Вадим К (статус: Академик), 6 января 2010, 18:21 [#9]:

Настройки компилятора тут точно не помогут. но фраза "лазил в компиляторе - не помогло" - это круто. Работает разработчиком компилятора делфи???:)))
Посмотрел я на код внимательней и думаю, что лучше стоит применить старый известный метод, не изобретать проблему на свою голову. Строковый тип это так называемый magic type - то есть компилятор там вставляет много своего кода на фоне, что бы обеспечить прозрачную работу. А когда мы пытаемся его обмануть, получаем по голове.
Обычно эту проблему решают так. Заводят записи (они же record) вида
type
  Answer = record
    tip:integer;
  end;
  AnswerA = record
    tip:integer;
    rez:string;
  end;
 
  AnswerB = record
    tip:integer;
    rez1:string;
    rez2:integer;

код в длл возвращает указатель на одну с таких структур. (его лучше через new создать). в поле tip вписывает число-константу, которое потом вызываемым кодом может использоваться для анализа правильности. А остальные поля заполняет по потребности. Единственное, что бы первое поле всегда занимало 4 байта в каждой структуре для ответа.
Вызываемый код очищает память от структуры вызовом dispose.

Если быть ещё культурней, то структуру должен создавать и передавать вызывающий код, а потом и удалять. (правило - сам создал, сам и чисти).
Галочка "подтверждения прочтения" - вселенское зло.
MOZGIII

MOZGIII (статус: Посетитель), 6 января 2010, 21:30 [#10]:

Сработало, спасибо огромное!

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:55
Выполнено за 0.03 сек.