主页
Top.Mail.Ru Yandeks.Metrika
论坛:“基地”;
当前存档:2002.07.29;
下载:[xml.tar.bz2];

向下

IB SQL UDF 找到类似的分支


Nebula   (2002-07-05 14:51) [0]

Продолжение вопроса. Библиотеку создал, функция возвращает строку.

function MyUDF: string;
开始
result := "text";
结束;

в IB описал.

DECLARE EXTERNAL FUNCTION NEBULA
RETURNS VARCHAR(1024) CHARACTER SET WIN1251
ENTRY_POINT "MyUDF"
MODULE_NAME "path\MyUDF.dll"

Как вызвать-то? select MyUDF не работает.



Val   (2002-07-05 15:02) [1]

а почему вы так ее вызываете? вы же select sum не пишите, к примеру?



Johnmen   (2002-07-05 15:03) [2]

1. dll должна лежать в соотв. месте
2. Может всетаки использовать уже существующие библиотеки ?



kaif   (2002-07-05 15:10) [3]

Нужно аллокировать память (GetMem) под строку, PChar возвращать, а не string и использовать FREE_IT в объявлении UDF. Функцию объявить как stdcall и экспортировать из dll (export).



Nebula   (2002-07-05 15:42) [4]

2Johnmen. С огромным удовольствием! Какую библиотеку использовать?



Johnmen   (2002-07-05 15:48) [5]

ib_udf.dll



Digitman   (2002-07-05 17:35) [6]

Небольшое замечание к kaif © (05.07.02 15:10)

спецификатор free_it вовсе не является обязательным при возврате чего-либо, в дан. случае - строки.

данный спецификатор требуется для указания IB-ядру сервера о необходимости автоматически освобождать блок памяти выделенный в теле UDF для передачи некоего (произвольного типа, в 1-ю очередь - строкового) возвращаемого параметра, после того, как значение возвращенного параметра буде считано из результирующего блока памяти. Если этого не сделать, возникнут утечки памяти и последствия работы сервера будут непредсказуемыми.



kaif   (2002-07-05 17:46) [7]

>2 Digitman.
Я знаю. Правда я думал, что FREE_IT используется исключительно для строк...

Кстати, спасибо за пример FormatDateTime. Он заработал.
Потом немного мучился с FormatFloat...
В конце концов удалось наконец принять в dll тип
DOUBLE PRECISION:

function FmtIBDouble(FmtStr: PChar; Value: Pointer): PChar; stdcall;
VAR
Tmp: String;
开始
尝试
Tmp:= FormatFloat(String(FmtStr), Double(Value^));
......等

Странно, но передача по ссылке (const Value: double) не работала. Я уже не первый раз с этим сталкиваюсь при работе с dll. Разве это не то же самое, что и разыменование указателя?
Видно я чего-то фундаментального не знаю о передаче параметров по ссылке...



Digitman   (2002-07-05 18:22) [8]

>>фундаментального не знаю о передаче параметров по ссылке...

Эт точно) ... но - самокритично и вызывает неподдельное уважение.

Правило №1 (выучи как Отче Наш - очень поможет в дальнейшем):

абсолютно все факт.параметры передаются ядром IB-сервера в UDF ссылкой (указателем) на местоположение в АП сервера ВРЕМЕННОЙ КОПИИ оригинальных параметров.

Отсюда прямой вывод :

Объявление параметров в самой UDF должно делаться ,как минимум, двумя способами (возьмем для примера тот же Double)

1. var Value: Double
2. [const] Value: PDouble, где PDouble = ^Double;

[const] - необязательный спецификатор, разницы в том, есть он или отсутствует, в случае с UDF - абсолютно никакой

Соответственно, обращение из UDF к заначениям переданных параметров должно выглядеть след.образом :


1. SomeLocalVar := Value;
2. SomeLocalVar := Value^; вот оно, разыменование прямого указателя


Дабы не влипнуть в AV, следует еще и такую вещь всегда принимать во внимание : если передаваемый факт.параметр = Null, то в UDF передается nil, а проверить это во избежание AV оч.просто :

1. if Assigned(@Value) then ...

@ - это перекрытие действий компилятора по-умолчанию, который без "барана" в лучшем случае будет проверять на nil не переданную ссылку, а то что лежит фактически по этой ссылке, в худшем - вообще откажется компилировать

2. if Assigned(Value) then ...


Еще один важный момент : никаких stdcall в декларации экспортируемых ф-ций ! Только CDECL будет работать правильно ! Почему ? Загляни в хэлп в топик "calling conventions" - сразу станут ясны различия с учетом того, что IB-ядро использует C-соглашения о вызовах и балансе стека при возврате из вызываемой cdecl-ф-ции



Digitman   (2002-07-05 18:28) [9]

Небольшое уточнение : правило передачи Null-параметров на строковые параметры не распространяется, и if Assigned(..) в таких случаях всегда даст True, потому как передается адрес ВРЕМЕННОГО блока памяти, содержащего на момент вызова UDF единственный символ - #0 (терминатор строки)



kaif   (2002-07-06 02:26) [10]

> 2 Digitman
Спасибо за подробные объяснения. Особенно насчет способа вызова. Дело в том, что у меня вызовы stdcall срабатывают в Interbase и мои UDF-ы работают без видимых признаков проблем. Мне и в голову не пришло, что IB требует cdecl. Я по привычке вписал stdcall. Я знал разницу в принципах этих вызовов, но мне казалось, что все приложения Win32 как правило используют stdcall, по крайней мере все API. А вот, выясняется, что IB действует иначе...
Сейчас еще посмотрю, что у меня с NULL происходит (забыл проверить). То есть строковый NULL это просто пустая строка? Но ведь IB различает значения "" и NULL. Или это только при передаче параметров то же самое?



Страницы: 1 整个分支

论坛:“基地”;
当前存档:2002.07.29;
下载:[xml.tar.bz2];

楼上









内存:0.59 MB
时间:0.041 c
1-95371
XYZ
2002-07-15 21:02
2002.07.29
对象又是什么?


3-95189
库兹涅佐夫
2002-07-05 14:35
2002.07.29
要求他们不好


4-95610
KSergey
2002-05-22 15:37
2002.07.29
从dll调用另一个dll中的f-tion


14-95560
莱昂
2002-07-04 12:38
2002.07.29
扫描仪


1-95424
方向盘
2002-07-15 19:11
2002.07.29
自动启动Excel





南非荷兰语 阿尔巴尼亚人 阿拉伯语 亚美尼亚 阿塞拜疆 巴斯克 白俄罗斯 保加利亚语 加泰罗尼亚 简体中文 中国(繁体) 克罗地亚 捷克 丹麦语 荷兰人 英语 爱沙尼亚语 菲律宾人 芬兰 法文
加利亚西语 格鲁吉亚语 德语 希腊语 海地克里奥尔语 希伯来语 印地语 匈牙利 北日耳曼语 印度尼西亚人 爱尔兰语 意大利语 日本性玩偶 韩语 拉脱维亚 立陶宛 马其顿 马来语 马耳他语 挪威语
波斯语 波兰语 葡萄牙语 罗马尼亚 俄语 塞尔维亚 斯洛伐克 斯洛文尼亚 西班牙语 斯瓦希里 瑞典语 泰国人 土耳其 乌克兰 乌尔都语 越南人 威尔士语 意第绪语 孟加拉 波斯尼亚
宿务 世界语 古吉拉特语 豪萨语 苗族 伊博 爪哇 卡纳达语 高棉 老挝 拉丁语 毛利 马拉 蒙古人 尼泊尔 旁遮普 索马里 泰米尔人 泰卢固语 约鲁巴语
祖鲁
英文 Французский Немецкий Итальянский Португальский 俄文 Испанский