Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Вызов функции из DLL. Мистика [WinXP]


pasha_golub ©   (2012-02-17 14:11:00) 

Друзья, конечно же мистики быть не может, но мой мозг устал. Взываю к ноосфере.

Имеем:

PGconn *PQconnectdbParams(const char **keywords, const char **values, int expand_dbname);


Обявляем у себя:
type  TPQconnectdbParams = function(Keywords: PPAnsiChar; Values: PPAnsichar; ExpandDBName: integer): PPGconn; cdecl;

var TPQconnectdbParams: TPQconnectdbParams


Используем:

function _PQConnectDBParams(AParams: TStrings; ExpandDbName: boolean = False): PPGConn;
var
 ConnKeywords, ConnValues: packed array of PAnsiChar;
 K,V: AnsiString;
 i: integer;
begin
 SetLength(ConnKeywords, AParams.Count);
 SetLength(ConnValues, AParams.Count);
 for i := 0 to AParams.Count - 1 do
  begin
    K := UTF8Encode(AParams.Names[i]); //since this is connection assume we'll use UTF8
    GetMem(ConnKeywords[i], Length(K) + 1);
    StrPCopy(ConnKeywords[i], K);
    V := UTF8Encode(AParams.ValueFromIndex[i]);
    GetMem(ConnValues[i], Length(V) + 1);
    StrPCopy(ConnValues[i], V);
  end;
  try
    Result := PQconnectdbParams(@ConnKeywords[0], @ConnValues[0], ord(ExpandDbName));
  finally
    for i := 0 to AParams.Count - 1 do
     begin
      FreeMem(ConnValues[i]);
      FreeMem(ConnKeywords[i]);
     end;
  end;
end;


Но беда. Иногда, при чем фиг пойми при каких условиях, первый вызов не работает. То есть возвращается nil, а повторный работает. На некоторых машинах в ответ выдается такая ошибка, что существует подозрение на неверно сконструированные параметры.

Я знаю, как это переписать и есть рабочий код. Но тысяча чертей! Что тут не так?


pasha_golub   (2012-02-17 14:32:00) [1]


> icWasya ©   (17.02.12 14:16) [1]

Василий, ты гений! С меня пивас! И того получилось:
function _PQConnectDBParams(AParams: TStrings; ExpandDbName: boolean = False): PPGConn;
var
 ConnKeywords, ConnValues: packed array of PAnsiChar;
 K,V: AnsiString;
 i: integer;
begin
 SetLength(ConnKeywords, AParams.Count + 1);
 SetLength(ConnValues, AParams.Count + 1);
 for i := 0 to AParams.Count - 1 do
  begin
    K := UTF8Encode(AParams.Names[i]); //since this is connection assume we'll use UTF8
    GetMem(ConnKeywords[i], Length(K) + 1);
    StrPCopy(ConnKeywords[i], K);
    {$IFDEF DELPHI_7}
    V := UTF8Encode(AParams.ValueFromIndex[i]);
    GetMem(ConnValues[i], Length(V) + 1);
    StrPCopy(ConnValues[i], V);
  end;
  try
    ConnKeywords[High(ConnKeywords)] := nil; //icWasya is a God!
    ConnValues[High(ConnValues)] := nil; //icWasya is a God!
    Result := PQconnectdbParams(@ConnKeywords[0], @ConnValues[0], ord(ExpandDbName));
  finally
    for i := 0 to AParams.Count - 1 do
     begin
      FreeMem(ConnValues[i]);
      FreeMem(ConnKeywords[i]);
     end;
  end;
end;


pasha_golub   (2012-02-17 14:21:00) [2]


> сколько символов копирует StrPCopy

Копирует Length(str) и завершает нулем.


jack128_   (2012-02-17 14:20:00) [3]

сколько символов копирует StrPCopy ?? Length(Str) или Length(Str) + 1 ??  Если первое, то у тя нет гарантии, что строки нулем заканчиваются..


pasha_golub   (2012-02-17 14:20:00) [4]


> Может быть в конце надо добавить нулевой элемент?

Логично, чтоб мне на Бейсике всю жизнь программировать! Щас попробую


icWasya   (2012-02-17 14:16:00) [5]

Не знаю что это за DLL, но, навскидку, а как она определяет размер массива Keywords и Values? Может быть в конце надо добавить нулевой элемент?


Наверх

Титульная страница Поиск, карта сайта Написать письмо