Модераторы: Akella
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Соглашение вызова в UDF-библиотеке, Передается что-то вроде указателя... 
:(
    Опции темы
Sister
Дата 17.5.2006, 01:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 23.9.2005

Репутация: нет
Всего: нет



Проблема вот в чем. Создал UDF dll-ку, сервером функция из нее вызывается, возвращаемое значение адекватно получаему параметру, но вот сам параметр не передается (точнее передается что-то вроде его адреса).

UDF: Тип параметра - INTEGER, возвращает CSTRING(30).

Тестировал dll-ку в Delphi, все получается нормально, когда соглашения вызова совпадают и в библиотеке и в программе, но что касается сервера БД, то он при некоторых соглашниях вызова, установленных в библиотеке, отказывается работать. Какое соглашение должно быть? 
PM MAIL   Вверх
TheCetus
Дата 17.5.2006, 09:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 134
Регистрация: 9.3.2006

Репутация: нет
Всего: 2



DECLARE EXTERNAL FUNCTION CET_POSEX
  CSTRING(250), CSTRING(32767), INTEGER
RETURNS
  INTEGER BY VALUE
ENTRY_POINT 'Cet_PosEx' MODULE_NAME 'cet_udf';

вроде на форуме где то лежала статья как UDFы писать

Добавлено @ 09:45 
DECLARE EXTERNAL FUNCTION CET_GET_PARAMITEM
  CSTRING(1), CSTRING(32767), INTEGER
RETURNS
  CSTRING(250) FREE_IT
ENTRY_POINT 'Cet_Get_ParamItem' MODULE_NAME 'cet_udf';

Добавлено @ 09:47 
а еще лучше покажи скрипты регистрации функций, код самих функций и параметры при которых все падает
 
PM MAIL   Вверх
Sister
Дата 18.5.2006, 21:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 23.9.2005

Репутация: нет
Всего: нет



Код dll:

library Project2;
uses SysUtils, Classes;
{$R *.res}

function GetNameOfPeriod(days: integer): PChar; export;
begin
//остальной код, первым делом проверяю days - оно вообще не то, которое передается
end;

exports  GetNameOfPeriod;
begin end.

Скрипт регистрации:
DECLARE EXTERNAL FUNCTION u_getname
    INTEGER
RETURNS CSTRING(30)
ENTRY_POINT 'GetNameOfPeriod' MODULE_NAME 'Project2';

Любой параметр типа integer передается неверно, например, так:

SELECT rdate, content, tim, u_getname(tim) 
FROM requests;
где tim определен как integer.

Что интересно, так это то, что при соглашении вызова cdecl правильно передаются строки CSTRING(XXX), но неправильно - числа. А если соглашение принимается таким, какое оно по умолчанию, то вообще ничего из них не передается верно (пробовал только строки и числа).
 
PM MAIL   Вверх
TheCetus
Дата 19.5.2006, 12:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 134
Регистрация: 9.3.2006

Репутация: нет
Всего: 2



Код

library Cet_UDF;

function malloc(Size: Integer): PChar; cdecl; external 'msvcrt.dll';


function Cet_Char(a:byte) : PChar; cdecl export;
var
  s : string;
begin
  s := Chr(a);
  Result := malloc(2);
  StrPCopy(Result, s);
end;


Exports
  Cet_Char;

End.



Код

DECLARE EXTERNAL FUNCTION CET_CHAR
  INTEGER
RETURNS
  CSTRING(10) FREE_IT
ENTRY_POINT 'Cet_Char' MODULE_NAME 'cet_udf';


Добавлено @ 12:14 
у меня при сипользовании cdecl все нормально передается 
PM MAIL   Вверх
Sister
Дата 19.5.2006, 20:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 23.9.2005

Репутация: нет
Всего: нет



2TheCetus: передаешь INTEGER, а принимаешь byte. Почему? 
Хотя это и не имеет большого значения, я думаю. 

Это сообщение отредактировал(а) Sister - 19.5.2006, 21:16
PM MAIL   Вверх
Sister
Дата 19.5.2006, 21:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 23.9.2005

Репутация: нет
Всего: нет



Показательный пример:
Код

library Project2;

uses  SysUtils,  Classes;

{$R *.res}

function ReturnParam(a: integer): integer; cdecl; export;
begin
Result:=a;
end;

exports  ReturnParam; 

begin end.


Скомпилированная dll помещается в ...Firebird_1_5\UDF
Скрипты БД:
Код

CREATE TABLE REQUESTS (
    ID       INTEGER NOT NULL,
    RDATE    DATE,
    CONTENT  VARCHAR(50),
    TIM      INTEGER,
    ID_BR    INTEGER,
    ID_P     INTEGER
);


DECLARE EXTERNAL FUNCTION "u_ReturnParam"
    INTEGER
RETURNS INTEGER BY VALUE
ENTRY_POINT 'ReturnParam' MODULE_NAME 'Project2';


Результаты следующего запроса:
       
Код

SELECT tim, "u_ReturnParam"(tim)
       FROM requests;


TIM  u_ReturnParam  
  3     17 692 540  
  5     17 692 540  
  2     17 692 540  
  7     17 692 540  
  7     17 692 540  
  2     17 692 540  
  3     17 692 540  
  1     17 692 540  
  3     17 692 540  
  2     17 692 540  
  3     17 692 540
   
PM MAIL   Вверх
TheCetus
Дата 22.5.2006, 09:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 134
Регистрация: 9.3.2006

Репутация: нет
Всего: 2



короче, вот решение:


Код


function ReturnParam(var a: integer): integer; cdecl; export;
begin
Result:=a;
end;



все параметы передаваемые по значению должны именно так и передаваться )
т.е. параметры типа integer, byte должны быть описаны с VAR


P.S. Посмотрел, у меня в проекте функция Cet_Char не использовуется, поэтому баг не заметил сразу 
PM MAIL   Вверх
Sister
Дата 28.5.2006, 03:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 23.9.2005

Репутация: нет
Всего: нет



Цитата

все параметы передаваемые по значению должны именно так и передаваться

А уверен, что по значению, ведь var - это передача по ссылке.

 Я пробовал так делать, но не получалось может быть из-за того, что я изменял и соглашение и писал var безсистемно, не проверив всех вариантов, один из которых мог оказаться удачным. 

И чем параметры integer и byte так выделяются?

И еще - чтобы передавать параметр не по ссылке, надо в объявлении функции в БД после указания его типа писать BY VALUE ?

Так или иначе, это мне уже не нужно, но теперь просто интересно узнать, как все это правильно делается. 
PM MAIL   Вверх
TheCetus
Дата 29.5.2006, 09:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 134
Регистрация: 9.3.2006

Репутация: нет
Всего: 2



точно, описАлся... по ссылке...

вот работающий код UDF функции
Код

function Cet_PosEx(aSubStr : PChar ;aStr : PChar; var Idx : integer) : integer; cdecl export;
begin
  Result := PosEx(aSubStr, aStr, Idx);
  Idx := Result + 1;
end;


Код

DECLARE EXTERNAL FUNCTION CET_POSEX
  CSTRING(250), CSTRING(32767), INTEGER
RETURNS
  INTEGER BY VALUE
ENTRY_POINT 'Cet_PosEx' MODULE_NAME 'cet_udf';

значение возвращается по значению, а не по ссылке
передается по ссылке
строки передаются как PChar...

вприницпе тут где то была статья как писАть UDF функции, там все достаточно хорошо расписано...
свою библиотеку писал по этой статье 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Interbase"
Alex

Обязательно указание:

1. Версию InterBase (Firebird, Yaffil)

2. Способа доступа (ADO, BDE, IBX и т.д.)

  • КАК ПРАВИЛЬНО ОФОРМИТЬ КОД - ЗДЕСЬ
  • КАК ПРАВИЛЬНО УКАЗАТЬ ТЕКСТ ОШИБКИ - ЗДЕСЬ
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • FAQ раздела лежит здесь!

Если Вам понравилась атмосфера форума, заходите к нам чаще! С Уважением, Akella.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Firebird, Interbase | Следующая тема »


 




[ Время генерации скрипта: 0.0469 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.