Russian Qt Forum

Qt => Базы данных => Тема начата: ecspertiza от Октябрь 20, 2009, 11:40



Название: Qt работа с UDF
Отправлено: ecspertiza от Октябрь 20, 2009, 11:40
Вопрос таков, возможно ли на Qt написать udf-ку для firebird ???

Я пробовал сделать вот так
Код:
extern "C"
{
    char* result(char* );
}

char* result(char* a)
{
    return a;
}

И затем объявление в самом Firebird, так все работает на ура, но если я в Qt подключаю хотя бы
Код:
#include <iostrem>

то во-первых размер длл-ки увеличивается в 10 раз, и сразу же вызов функции из БД невозможен, БД пишет мол нет такой ф-ции. При этом смотрю через TotalCommander в длл-ке кроме моей ф-ции появляются еше какие то сторонние .Может подскажете советом.


Название: Re: Qt работа с UDF
Отправлено: Zmeishe от Октябрь 20, 2009, 11:53
Моя UDF работает без проблем и на Linux и на Win

Вот пример с одной стандартной функцией pow(...) из #include <math.h>
и одной Qt функцией qRound64(...) из #include <QtCore/QtGlobal>


ib_round.cpp
Код:
#include <QtCore/QtGlobal>
#include <math.h>

#ifdef Q_OS_WIN
# if defined( QT_BUILD_MATH_LIB )
# define Q_MATH_EXPORT __declspec(dllexport)
# else
# define Q_MATH_EXPORT __declspec(dllimport)
# endif
#else
# define Q_MATH_EXPORT
#endif  


extern "C" Q_MATH_EXPORT double ib_udf_round_to(double *x, int *y)
{
 double p = pow(10.0, *y);
 return qRound64(*x * p) / p;
}

ib_round.pro
Код:
...
win32 {
 DEFINES +=  QT_BUILD_MATH_LIB
}
...


Название: Re: Qt работа с UDF
Отправлено: ecspertiza от Октябрь 20, 2009, 12:54
При работе с числами у меня тоже проблем нету, но мне нужно работать со строками, и если я хоть в одном месте объявляю Qt шную строку
Код:
QString str;

или C++
Код:
#include <string>
std::string str;

то все смерть, функция невидна и т.д и т.п.



Название: Re: Qt работа с UDF
Отправлено: break от Октябрь 20, 2009, 13:17
создается такое впечатление как будто ваша DLL с UDF не линкуется со всякими QtCore - попробуйте использовать свою DLL-UDF другой тестовой программой, которая попытается вызвать эту же ф-ю.


Название: Re: Qt работа с UDF
Отправлено: Zmeishe от Октябрь 20, 2009, 13:56
При работе с числами у меня тоже проблем нету...
А при работе с числами ты какие Qt-шные функции используешь?


Название: Re: Qt работа с UDF
Отправлено: ecspertiza от Октябрь 20, 2009, 14:29
создается такое впечатление как будто ваша DLL с UDF не линкуется со всякими QtCore - попробуйте использовать свою DLL-UDF другой тестовой программой, которая попытается вызвать эту же ф-ю.

пробовал написать просто тестовую софтину, тоже ку-те-шную которая вызавыет ф-ции, все нормально отрабатывает.

Цитировать
А при работе с числами ты какие Qt-шные функции используешь?

Ну на самом, деле при работе с числами именно ку-тешные ф-ции не юзаю, ибо чистого C++ хватает, а тут строку нужно закодировать и самое простое на мой взгляд это

Код:
QByteArray::toString()

И стало быть QString тоже нужно использовать, но вот как только так сразу и не работает >:(

Свою реализацию base64 писать не хочется нашел на C++ там используется std::string , но вот как только его использовать  то сразу вход в функцию из Firebird не найден, а если свою софтину написать то все отлично работает.


Название: Re: Qt работа с UDF
Отправлено: Zmeishe от Октябрь 20, 2009, 14:43
Цитировать
А при работе с числами ты какие Qt-шные функции используешь?

Ну на самом, деле при работе с числами именно ку-тешные ф-ции не юзаю, ибо чистого C++ хватает, а тут строку нужно закодировать и самое простое на мой взгляд это
Сделай UDF, как у меня, с числами и с qRound() / qRound64()
И скажи - работает или нет.
Если не работает, то процесс interbase / firebird не видит Qt*.dll
Для Win пропиши переменную PATH


Название: Re: Qt работа с UDF
Отправлено: ecspertiza от Октябрь 20, 2009, 14:47
Переменная прописана, и твой пример работает отлично, но со строками проблема дай путь...


Название: Re: Qt работа с UDF
Отправлено: Zmeishe от Октябрь 20, 2009, 14:56
Ну прям, не знаю.

Есть у меня ещё вот такая - и тоже работает не один год
Код:
extern "C"  __declspec(dllexport) char* ib_udf_createUUID()
{
  char *p;
 
  p = QUuid::createUuid().toString().toLatin1().data();
  return p;
}

Заметь - toString() нормально юзается.


Название: Re: Qt работа с UDF
Отправлено: ecspertiza от Октябрь 20, 2009, 15:22
Вот все и не работает.

в общем делаю вот так

Qt код
Код:
#include <QtCore/QtGlobal>
#include <QUuid>

#ifdef Q_OS_WIN
# if defined( QT_BUILD_MATH_LIB )
# define Q_MATH_EXPORT __declspec(dllexport)
# else
# define Q_MATH_EXPORT __declspec(dllimport)
# endif
#else
# define Q_MATH_EXPORT
#endif

extern "C"  __declspec(dllexport) char* ib_udf_createUUID()
{
  char *p;

  p = QUuid::createUuid().toString().toLatin1().data();
  return p;
}

декларация в Firebird
Код:
DECLARE EXTERNAL FUNCTION UDF
RETURNS CSTRING(254) FREE_IT
ENTRY_POINT 'ib_udf_createUUID' MODULE_NAME 'crqphudf';

длл-ка лежит где нужно, при вызове
Код:
select UDF() from Object

говорит что точка входа в длл не найдена, может ешё что то нужно?


Название: Re: Qt работа с UDF
Отправлено: BRE от Октябрь 20, 2009, 15:27
Код:
extern "C"  __declspec(dllexport) char* ib_udf_createUUID()
{
  char *p;
 
  p = QUuid::createUuid().toString().toLatin1().data();
  return p;
}
Нормально работает не один год....
Поищи по форуму темы про подобные конструкции: .toLatin1().data();
Несколько раз обсуждалось, что так делать не стоит.


Название: Re: Qt работа с UDF
Отправлено: Zmeishe от Октябрь 20, 2009, 15:34
Цитата: BRE
Поищи по форуму темы про подобные конструкции: .toLatin1().data();
Несколько раз обсуждалось, что так делать не стоит.
Знаю я. Просто для ecspertiza урезал код. Задача была показать, что со строками всё должно работать.

На самом деле если в базе данных создаёшь UDF с ключиком FREE_IT
следует делать так:

Код:
#include <QtCore/QtGlobal>
#include <QtCore/QUuid>
#include <ib_util.h>

extern "C"  __declspec(dllexport) char* ib_udf_createUUID()
{
  char *p, *buf;

  p = QUuid::createUuid().toString().toLatin1().data();
  buf = (char*) ib_util_malloc(64);

  затем перегоняешь из p в buf

  return buf;
}

Но это так, к сведению.

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



Название: Re: Qt работа с UDF
Отправлено: BRE от Октябрь 20, 2009, 15:49
Вот у меня тоже такое впечатление:
создается такое впечатление как будто ваша DLL с UDF не линкуется со всякими QtCore

2 ecspertiza
Покажи пожалуйста код библиотеки с UDF + файл проекта (.pro)


Название: Re: Qt работа с UDF
Отправлено: ecspertiza от Октябрь 20, 2009, 16:05
Допустим вот так

*.cpp
Код:
#include <QtCore/QtGlobal>
#include <QDebug>

extern "C" __declspec(dllexport) char* tostring(char* str)
{
  QByteArray data(str);
  data = data.toBase64();

  char *p = new char();

  p = data.data();

  qDebug() << p;

  return p;
}

*.pro
Код:
QT -= gui
QT += core
TARGET = crqphudf
TEMPLATE = lib
DEFINES += CRQPHUDF_LIBRARY
SOURCES += crqphudf.cpp
HEADERS +=
CONFIG += release

что самое интересное, сейчас начал вызывать функцию просто из другой софтины
вот так
Код:
    typedef char* (*toBase)(char *);
    toBase tobase = (toBase) QLibrary::resolve("crqphudf","tostring");

    char* base = tobase("qwerty");

    qDebug() << "key" << base;

в этом месте
Код:
qDebug() << p;
получаю нормальный результат

а тут
Код:
qDebug() << "key" << base;

один символ, при этом если из длл-ки убрать QByteArray

и оставить просто
Код:
  char *p = new char();
  p = str;
  return p;

то все работает нормально ???




Название: Re: Qt работа с UDF
Отправлено: BRE от Октябрь 20, 2009, 16:10
Из другой софтины функция находиться, а из базы нет?

На счет странностей:
char *p = new char();   // здесь ты выделил один байт и присвоил его указателю p
p = data.data();      // здесь ты указатель p настроил на другую область памяти (предыдущая память потерялась)


Название: Re: Qt работа с UDF
Отправлено: Zmeishe от Октябрь 20, 2009, 16:13
Переменная типа QByteArray это локальная переменная внутри твоей функции.
После return указатель data.data() уже мертв!

Где ты видел, чтобы локальные переменные так возвращали.

Но это к делу не относится.
Я не понимаю, почему Firebird  не может с твоими DLL работать.
Такое ощущение, что у твоей DLL есть ещё какие-то зависимости от других DLL и Firebird не имеет к ним доступа.

Как собрана Qt и чем она собрана ?


Название: Re: Qt работа с UDF
Отправлено: ecspertiza от Октябрь 20, 2009, 16:23
Из другой софтины функция находиться, а из базы нет?

Именно, это меня и пугает.

все зависимости есть в TotalCommander
Код:
kernel32.dll
mingw10.dll
msvctrl.dll
QtCore4.dll


Название: Re: Qt работа с UDF
Отправлено: BRE от Октябрь 20, 2009, 16:25
Именно, это меня и пугает.
А как из FB ее дергаешь, может там что не так.


Название: Re: Qt работа с UDF
Отправлено: Zmeishe от Октябрь 20, 2009, 16:27
PATH к mingw10.dll прописан? Firebird до неё может достучаться?


Название: Re: Qt работа с UDF
Отправлено: Tonal от Октябрь 21, 2009, 08:26
Посмотри Filemon-ом чё дёргается серверо мри попытке вызвать UDF-ку.
Похоже каких-то dll-ек не находит.
Ну и сообщение сервера об ошибке надо бы привести, однако. :)


Название: Re: Qt работа с UDF
Отправлено: ecspertiza от Октябрь 21, 2009, 10:59
Вот скрин ошибки
http://pic.ipicture.ru/uploads/091021/OOknhxNixD.jpg

Цитировать
PATH к mingw10.dll прописан?
Да

Цитировать
Firebird до неё может достучаться?

Не знаю как посмотреть

Цитировать
А как из FB ее дергаешь, может там что не так.

пробую реализовать пример Zmeishe
Код:
extern "C" __declspec(dllexport) char* uid()
{
  char *p;

  p = QUuid::createUuid().toString().toAscii().data();
  return p;
}

в Firebird декларирую вот так
Код:
DECLARE EXTERNAL FUNCTION UDF
  RETURNS CSTRING(254)
  ENTRY_POINT 'uid'
  MODULE_NAME 'crqphudf'

Вызываю так
Код:
select UDF() from Object

получаю ошибку выше, в место Filemon, скачал Process Monitor ибо у меня Vista, пока с ним разбираюсь.




Название: Re: Qt работа с UDF
Отправлено: ecspertiza от Октябрь 21, 2009, 11:37
вот что мне говорит Process Monitor http://pic.ipicture.ru/uploads/091021/0oHA6pj07X.jpg


Название: Re: Qt работа с UDF
Отправлено: Zmeishe от Октябрь 21, 2009, 11:51
У тебя там два модуля(файла) ? Один с расширением dll, другой без ?
Я правильно понял? Или это Process Monitor так показывает?

Убей тот, который без расширения.


Название: Re: Qt работа с UDF
Отправлено: ecspertiza от Октябрь 21, 2009, 12:20
Модуль там один тот который с расширением dll.

Я думаю что в Firebird декларация идет как "crqphudf" вот он наверное и ищет сначала с без "dll" потом с "dll"


Название: Re: Qt работа с UDF
Отправлено: Zmeishe от Октябрь 21, 2009, 12:47
А чем вызываешь
select UDF() from Object
??



Название: Re: Qt работа с UDF
Отправлено: ecspertiza от Октябрь 21, 2009, 13:58
Сначала через IBExpert ,а сейчас через Interbase&Firebird Development Studio ошибка одна и та же. Firebird 2.1.3


Название: Re: Qt работа с UDF
Отправлено: Zmeishe от Октябрь 21, 2009, 14:16
Как же у тебя работал пример с udf, который с числами и функцией qRound64()  ???
Если бы он не работал, я бы решил, что дело в компиляторе.
А так, даже не знаю.
Должно работать - у меня работает независимо от платформы Linux/Windows.
Только я НЕ на Vista, а XP проверял.

PS:
1 декабря 2009 г. будет ровно год, как я в Windows заходил последний раз.
Linux мне больше понравился.


Название: Re: Qt работа с UDF
Отправлено: ecspertiza от Октябрь 21, 2009, 15:05
офф.
Цитировать
1 декабря 2009 г. будет ровно год, как я в Windows заходил последний раз.

И у меня день рождение :)

В общем насколько я понял пример с числами работал потому что, компилятор не собирал либы или может еше что то что использует строки, ибо пример с числами весит 5кб а со строками 21кб,  если чесно я сам ничего понять не могу, хотелось использовать Qt в udf ибо проще ,а получилось сложнее :) Я просто написал свою реализацию алгоритмов шифрования, ибо все таки если использовать просто char* то все работает. Если есть еше какие соображения пишите буду признателен, если сам разберусь обязательно отпишу в Wiki.

Есть еше вопрос тоже оффтопом

При декларировании функции в Firebird необходимо указывать тип возвращаемого значения я указываю Cstring(255) а если строка будет длиннее то что тогда я же заранее не знаю размер строки как лучше задекларировать в этом случае?


Название: Re: Qt работа с UDF
Отправлено: Zmeishe от Октябрь 21, 2009, 15:20
Цитата: ecspertiza
пример с числами работал потому что, компилятор не собирал либы или может еше что то что использует строки
В моём примере qRound64() использует то же, что QString - QtCore4.dll
И если udf c qRound64() работает, т.е. все модули и точки входа FB находит, значит и с QString работать должен - разницы никакой.
Либо дело в связке FB + Vista.


Цитата: ecspertiza
а если строка будет длиннее то что тогда я же заранее не знаю размер строки как лучше задекларировать в этом случае?
Насколько я помню, в IB/FB можно задать большую длину строки 32000 или даже 64000.

Если этого мало - тогда юзай тип BLOB.