Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 23.12.2010, 09:27   #1
Alex Cones
Trust no one.
Старожил
 
Аватар для Alex Cones
 
Регистрация: 07.04.2009
Сообщений: 6,526
По умолчанию Передача "сгоревших" PChar

При экспорте PChar из DLL в EXE использую строку в глобальном хранилище, а при получении вызываю экспортнутую MyDispose.

А вот обратно (из EXE в DLL) такая техника не сработает по причине того, что я не буду иметь возможно просигналить, что функа получена.

Проблема - переделать PChar на String в вызове функции:

Код:
{002} Function CreateButton(FormName : PAnsiChar):Integer; OverLoad;
Код:
{001} Function DLL_CreateButton(FNum : Integer; FName : PAnsiChar; UseName : LongBool; BName : PAnsiChar) : Integer; StdCall; External 'Gfur.dll' Name 'CreateButton';
Код:
Function CreateButton(FormName : PAnsiChar):Integer; OverLoad;
 Begin
  Result := DLL_CreateButton(0, PAnsiChar(FormName), TRUE, '');
 End;
P.S. При передаче DLL -> EXE я сделал так:
Код:
{055} Function IntToStr(Int : Integer): String; OverLoad;
Код:
{024} Procedure DLL_IntToStr(I : Integer; Width : Integer; Var Res : PAnsiChar); StdCall; External 'Gfur.dll' Name 'IntToStr';
Код:
 Function IntToStr(Int : Integer): String; OverLoad;
 Var
  Str : PAnsiChar;
 Begin
  Str := '';
  DLL_IntToStr(Int, 0, Str); //Вертает PChar как параметр
  Result := String(Str);
  DLL_DisposeGlobalResult; //Обнуляет String в DLL
 End;
SQUARY PROJECT - НАБОР БЕСПЛАТНЫХ ПРОГРАММ ДЛЯ РАБОЧЕГО СТОЛА.
МОЙ БЛОГ
GRAY FUR FRAMEWORK - УДОБНАЯ И БЫСТРАЯ РАЗРАБОТКА WINAPI ПРИЛОЖЕНИЙ
Alex Cones вне форума Ответить с цитированием
Старый 23.12.2010, 18:59   #2
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

WideString не устроил?

Код:
Function CreateButton(FormName : PAnsiChar):Integer; OverLoad;
 Begin
  Result := DLL_CreateButton(0, PAnsiChar(FormName), TRUE, '');
 End;
Ээээ??? Наверное, должно быть:

Код:
Function CreateButton(const FormName : AnsiString):Integer; OverLoad;
begin
  Result := DLL_CreateButton(0, PAnsiChar(FormName), TRUE, '');
end;
Код:
Result := String(Str);
Это или неверно, или, как минимум, запутывающе (мне лень смотреть). Корректно:

Код:
Result := Str;
P.S.
Код:
DLL_DisposeGlobalResult
- нехорошо. Очень. А если в два потока вызовут? А если надо будет вернуть N строк? Надо явно указывать в параметре, что освобождаем.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 23.12.2010, 20:43   #3
Alex Cones
Trust no one.
Старожил
 
Аватар для Alex Cones
 
Регистрация: 07.04.2009
Сообщений: 6,526
По умолчанию

Цитата:
Надо явно указывать в параметре, что освобождаем.
Хорошо, сделаю.
Цитата:
WideString не устроил?
Он не во всех версиях есть.
Цитата:
Это или неверно, или, как минимум, запутывающе
Str - PAnsiChar, result - String.
Цитата:
Function CreateButton(const FormName : AnsiString):Integer; OverLoad;
begin
Result := DLL_CreateButton(0, PAnsiChar(FormName), TRUE, '');
end;
Эм... Я немного не ту функцию привел...
В функции выше я могу таким методом воспользоваться (Кстати, поясните, что даст const), а вот в такой - нет:
Код:
Function CreateButton(FormNumber : Integer; ButtonName : PAnsiChar):Integer; OverLoad;
 Begin
  Result := DLL_CreateButton(FormNumber, '', FALSE, PAnsiChar(ButtonName));
 End;
Здесь ButtonName переходит в структуру внутри DLL. Так как ButtonName здесь уйдет, то, по идее и умрет PAnsiChar, который внутри DLL.
SQUARY PROJECT - НАБОР БЕСПЛАТНЫХ ПРОГРАММ ДЛЯ РАБОЧЕГО СТОЛА.
МОЙ БЛОГ
GRAY FUR FRAMEWORK - УДОБНАЯ И БЫСТРАЯ РАЗРАБОТКА WINAPI ПРИЛОЖЕНИЙ
Alex Cones вне форума Ответить с цитированием
Старый 23.12.2010, 21:51   #4
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Цитата:
Он не во всех версиях есть.
Ээээ...? Это ты про Delphi 1 и Delphi 2? А ты уверен, что они тебе нужны?

Цитата:
Str - PAnsiChar, result - String.
Я вижу. Теперь подумай, что может означать String(Str).

Цитата:
Так как ButtonName здесь уйдет, то, по идее и умрет PAnsiChar, который внутри DLL
Тебе зачем PChar внутри DLL?

Ещё раз повторю правило:

PChar появляется только в момент передачи данных.

До и после - должен быть String.

Иными словами:

Код:
function DLL_CreateButton(FNum : Integer; FName : PAnsiChar; UseName : LongBool; BName : PAnsiChar) : Integer; StdCall;
var
  Name, ButtonName: String;
  // ...
begin
  Name := FName;
  ButtonName := BName;

  // ...
end;

Цитата:
Сообщение от Alex Cones Посмотреть сообщение
Кстати, поясните, что даст const
http://forum.vingrad.ru/forum/topic-...2107564/0.html
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.

Последний раз редактировалось GunSmoker; 23.12.2010 в 21:55.
GunSmoker вне форума Ответить с цитированием
Старый 24.12.2010, 10:34   #5
Alex Cones
Trust no one.
Старожил
 
Аватар для Alex Cones
 
Регистрация: 07.04.2009
Сообщений: 6,526
По умолчанию

Цитата:
Ээээ...? Это ты про Delphi 1 и Delphi 2? А ты уверен, что они тебе нужны?
И про D7 тоже. Поддержка UNICODE там сделана через одно место.
Цитата:
До и после - должен быть String.
Ясно, будет.
P.S. Я все равно не понимаю, что не так делает String(PCHAR)

НАчал переделывать и получаю AV каждый раз, когда пытаюсь заменить в модуле-связке PAnsiChar на AnsiString:
В DLL заменил все PAnsiChar в структурах на AnsiString. Откомпилировалось и пашет.

Так канает:
Код:
CreateForm(FALSE, 'Form1');
Код:
Function CreateForm(ShowOnTaskBar : LongBool; FormName : PAnsiChar):Integer; OverLoad;
 Begin
  Result := DLL_CreateForm(ShowOnTaskBar, FormName);
 End;
А так - AV:
Код:
CreateForm(FALSE, 'Form1');
Код:
Function CreateForm(ShowOnTaskBar : LongBool; FormName : AnsiString):Integer; OverLoad;
 Begin
  Result := DLL_CreateForm(ShowOnTaskBar, PAnsiChar(FormName));
 End;
SQUARY PROJECT - НАБОР БЕСПЛАТНЫХ ПРОГРАММ ДЛЯ РАБОЧЕГО СТОЛА.
МОЙ БЛОГ
GRAY FUR FRAMEWORK - УДОБНАЯ И БЫСТРАЯ РАЗРАБОТКА WINAPI ПРИЛОЖЕНИЙ

Последний раз редактировалось Stilet; 24.12.2010 в 20:49.
Alex Cones вне форума Ответить с цитированием
Старый 24.12.2010, 13:10   #6
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Цитата:
Сообщение от Alex Cones Посмотреть сообщение
Поддержка UNICODE там сделана через одно место.
Например?

Цитата:
Сообщение от Alex Cones Посмотреть сообщение
Я все равно не понимаю, что не так делает String(PCHAR)
Оке, пример-аналогия:

Код:
type
  TString = record
    Len: Integer;
    Data: array[0..5] of Char;
  end;
  PString = ^TString;

  TCharArray = record
    Data: array[0..5] of Char;
  end;
  PCharArray = ^TCharArray;

var
  PStr: PString;
  PChar: PCharArray;
  Str: TString;
  Char: TCharArray;
begin
  Char := ...;
  PChar := @Char;

  PStr := PString(PChar);

  Str := PStr^; // <- AV, либо мусор
end;
Может быть, String(PChar) и будет работать как ожидалось - вроде как компилятор понял, чего вы хотели. Но это как минимум очень неоднозначно и такой конструкции лучше избегать.

Код:
String := PChar; // - вполне нормально.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.

Последний раз редактировалось GunSmoker; 24.12.2010 в 13:13.
GunSmoker вне форума Ответить с цитированием
Старый 24.12.2010, 13:11   #7
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Цитата:
А так - AV:
Чего в DLL_CreateForm-то написано?
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 24.12.2010, 13:23   #8
Alex Cones
Trust no one.
Старожил
 
Аватар для Alex Cones
 
Регистрация: 07.04.2009
Сообщений: 6,526
По умолчанию

Код:
{002} Function DLL_CreateForm(OnTaskbar : LongBool; FName : PAnsiChar): Integer; StdCall; External 'Gfur.dll' Name 'CreateForm';
Код:
 Function CreateForm(OnTaskbar : LongBool; FName : PAnsiChar): Integer; StdCall; Export;
 Begin
  SetLength(Warehouse.Form, Length(Warehouse.Form) + 1);
  ...
  Warehouse.Form[Length(Warehouse.Form) - 1].Name := FName;
  ...
  Result := Length(Warehouse.Form) - 1;
 End;
SQUARY PROJECT - НАБОР БЕСПЛАТНЫХ ПРОГРАММ ДЛЯ РАБОЧЕГО СТОЛА.
МОЙ БЛОГ
GRAY FUR FRAMEWORK - УДОБНАЯ И БЫСТРАЯ РАЗРАБОТКА WINAPI ПРИЛОЖЕНИЙ
Alex Cones вне форума Ответить с цитированием
Старый 24.12.2010, 13:49   #9
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Если .Name - типа String, то проблема с AV не в строках.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 24.12.2010, 14:30   #10
Alex Cones
Trust no one.
Старожил
 
Аватар для Alex Cones
 
Регистрация: 07.04.2009
Сообщений: 6,526
По умолчанию

Он типа AnsiString, но AV появляется ведь, только когда я изменяю PAnsiChar на AnisCtring. И если я обращаюсь к форме по индексу, а не по имени, то все нормально.

UPD--------------------------------

Вот не поверите, по СВОЕЙ же фразе выше, понял, где ошибка.
Код:
 Function GetFormNumber(FName : PAnsiChar): Integer; StdCall; Export;
 Var
  I : Integer;
 Begin
  Result := VALUE_NOT_EXISTS;
  For I := 0 To Length(Warehouse.Form) - 1 Do
   If Warehouse.Form[I].Name = FName Then Result := I;
 End;
А надо:
Код:
 Function GetFormNumber(FName : PAnsiChar): Integer; StdCall; Export;
 Var
  I : Integer;
 Begin
  Result := VALUE_NOT_EXISTS;
  For I := 0 To Length(Warehouse.Form) - 1 Do
   If Warehouse.Form[I].Name = AnsiString(FName) Then Result := I;
 End;
Иначе идет сравнение адресов двух указателей. Вот и обращались по несуществующему индексу.
SQUARY PROJECT - НАБОР БЕСПЛАТНЫХ ПРОГРАММ ДЛЯ РАБОЧЕГО СТОЛА.
МОЙ БЛОГ
GRAY FUR FRAMEWORK - УДОБНАЯ И БЫСТРАЯ РАЗРАБОТКА WINAPI ПРИЛОЖЕНИЙ

Последний раз редактировалось Alex Cones; 24.12.2010 в 14:42.
Alex Cones вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как обойти "преобразование типа из "string" в "float" невозможно" lexluter1988 Помощь студентам 1 07.08.2010 12:23
"ОКРВВЕРХ", "ОКР", "ЕСЛИ". Как бы их связать. Каравай Microsoft Office Excel 13 17.02.2010 09:53
при вводе на листе "магазин"- код товара появлялось "описание" товара из "склада" с "продажной ценой" aleksei78 Microsoft Office Excel 13 25.08.2009 12:04
PCHAR строка с разделителями #13#10. Как вычленить отдельные "подстроки" EdNovice Общие вопросы Delphi 1 17.04.2007 11:42