![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Вызов функции из 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? Может быть в конце надо добавить нулевой элемент?