Russian Qt Forum
Ноябрь 24, 2024, 11:51 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2] 3 4 ... 7   Вниз
  Печать  
Автор Тема: [4.3.0-win] Как быть с dll?  (Прочитано 53477 раз)
Icoz
Гость
« Ответ #15 : Июль 27, 2007, 14:21 »

Цитата: "Alex Forth"
Цитата: "Icoz"
знаешь, для меня классический метод - это подрубить хидер, в файл *.pro добавить:
LIB += mylib
которая потом станет ключом -lmylib для псс
И ВСЕ!

Именно это я и имел ввиду Улыбающийся

Так именно для этого мне и нужен *.lib, из которого делается *.a, который уже линкуется! См. первый пост!
Записан
SABROG
Гость
« Ответ #16 : Июль 27, 2007, 14:22 »

Хидеры поставляемые к dllке есть ? Напиши парсер для хидера, который на основе прототипов функций будет выдавать твои:
Код:

typedef struct1* (*myfunc1)(int param1, char * param2);


А вордовский документ сохранить можно в обычный txt файл. Парсеру ведь не нужны красивости шрифтов и выравнивания по центру.
Записан
Icoz
Гость
« Ответ #17 : Июль 27, 2007, 14:30 »

Цитата: "SABROG"
Хидеры поставляемые к dllке есть ? Напиши парсер для хидера, который на основе прототипов функций будет выдавать твои:
Код:

typedef struct1* (*myfunc1)(int param1, char * param2);


А вордовский документ сохранить можно в обычный txt файл. Парсеру ведь не нужны красивости шрифтов и выравнивания по центру.

тоже верно, но хрен с ним с хидерами. Допустим у меня есть файл с описанием прототипов функций и фукция, которая их инициализирует:
Код:
typedef struct1* (*myfunc1)(int param1, char * param2); 
...
myfunc1 func1 = (myfunc1)QLibrary::resolve("my.dll","myfunc1");

Так отлично. Но мою проблему это не решает. Ибо мне на базе этих функций надо будет просто писать свою реализацию класса, который уже есть в dll. Итак, опять вопрос:
КАК ТОГДА ПОДГРУЗИТЬ КЛАСС???
Код:

myclass *cls = (myclass*)QLibrary::resolve("my.dll","myclass::myclass");

не работает.
Записан
Alex Forth
Гость
« Ответ #18 : Июль 27, 2007, 14:37 »

Цитата: "Icoz"
тоже верно, но хрен с ним с хидерами. Допустим у меня есть файл с описанием прототипов функций и фукция, которая их инициализирует:

Не, так дело не пойдет, это ключевой момент!!!
Вот представь ты в программе создаешь новый экземпляр класса из этой dll. Кмопилер должен знать скольк байт памяти надо выделить под экземпляр. Эту инфонрмацию можно получить только из декларации класса.

Цитировать
Итак, опять вопрос:
КАК ТОГДА ПОДГРУЗИТЬ КЛАСС???

Только по частям,  каждый метод отдельно в свой указатель на метод. Только как их потом организовать в класс???  :wink:
Записан
Icoz
Гость
« Ответ #19 : Июль 27, 2007, 14:41 »

Цитата: "Alex Forth"
Цитата: "Icoz"
тоже верно, но хрен с ним с хидерами. Допустим у меня есть файл с описанием прототипов функций и фукция, которая их инициализирует:

Не, так дело не пойдет, это ключевой момент!!!
Вот представь ты в программе создаешь новый экземпляр класса из этой dll. Кмопилер должен знать скольк байт памяти надо выделить под экземпляр. Эту инфонрмацию можно получить только из декларации класса.

Все декларации и прочее - все есть! Дайте код, как запустить конструктор, чтобы получить поинтер на класс! Кто поможет - с меня ПИВО!
Записан
Alex Forth
Гость
« Ответ #20 : Июль 27, 2007, 14:49 »

Цитата: "Icoz"
Дайте код, как запустить конструктор, чтобы получить поинтер на класс! Кто поможет - с меня ПИВО!


Примерно так:
Код:
void (SomeClass::*my_constructorc_ptr)(int, char*) = QLibrary::resolve("my.dll","void SomeClass::SomeClass(int, char*)");

Только насчет строки "void SomeClass::SomeClass(int, char*)" я не уврен, имена методов в библиотеках очень сильно перекручиваются. Тут надо курить мануал по mangle name

Впрочем один конструктор тебе не поможет.
Записан
Icoz
Гость
« Ответ #21 : Июль 27, 2007, 18:37 »

хм... доеду до дома, попробую. Но когда-то еще на qt4.0-4.1 я пытался так делать, у меня ничего не получилось. Да и в нете тогда по форумам искал, мне сказали, что классы из dll можно получить только подцепив lib.

Итак, а есть у кого мысли по сабжу. Как из dll сделать lib?
ибо я делаю *.a, а при компиляции линкер выводит:
Код:
... unresolved "myfunc1@8" ...

в def правлю строку с
Код:
myfunc1

на
Код:
myfunc1@8

Компилит, но прога при запуске говорит, что функция myfunc1 не найдена в библиотеке my.dll
Пробовал также:
Код:
myfunc1@8 = myfunc1

Тоже не катит

добавлено спустя 1 час 53 минуты:

 
Цитата: "Alex Forth"
Цитата: "Icoz"
Дайте код, как запустить конструктор, чтобы получить поинтер на класс! Кто поможет - с меня ПИВО!


Примерно так:
Код:
void (SomeClass::*my_constructorc_ptr)(int, char*) = QLibrary::resolve("my.dll","void SomeClass::SomeClass(int, char*)");

Только насчет строки "void SomeClass::SomeClass(int, char*)" я не уврен, имена методов в библиотеках очень сильно перекручиваются. Тут надо курить мануал по mangle name

Впрочем один конструктор тебе не поможет.

Вот строка - это самое главное!
В def'е она лежит как
Код:
@TMapAccess@$bctr@qv

Ни она, ни вариации на тему не работают. Попробовал так:
Код:
	QLibrary lib("mapacces");
QStringList lst;
lst << "@TMapAccess@$bctr$qv";
lst << "TMapAccess::bctr";
lst << "TMapAccess.bctr";
lst << "TMapAccess@$bctr";
lst << "@TMapAccess@ctr@qv";
lst << "@TMapAccess@$bctr@qv";
lst << "TMapAccess@$bctr@qv";
lst << "@TMapAccess@ctr";
lst << "@TMapAccess::ctr";
lst << "TMapAccess@ctr";
lst << "TMapAccess::ctr";
for (int i =0; i<lst.size(); i++){
TMapAccess_constructor map_constr = (TMapAccess_constructor)lib.resolve(lst[i].toAscii().constData());
if (map_constr){
QMessageBox::warning(0,"GOOD",QString("Here is function! %1").arg(i));
return;
}
}
QMessageBox::warning(0,"BAD","There is no function!");

Рад буду узнать любые предложения, как еще попробовать достать конструктор!

добавлено спустя 1 час 39 минут:

 УРА!
Код:
@TMapAccess@$bctr$qv
прокатило!
Только вот кто знает, что возвращает конструктор? Или что ему передавать?
ибо вызывая map_constr у меня в консоли при отладке вылезает
Код:
segmentation fault
in mapacces!@TMapControl@ShowBlockRstDevice$qqrr4TRmf
Записан
Alex Forth
Гость
« Ответ #22 : Июль 27, 2007, 23:12 »

Вызывать надо примерно так:
Код:

SomeClass *x = (SomeClass*)malloc( sizeof(SomeClass) );//new некатит т к компилер не может самостоятельно вызвать конструктор
(x->*my_constructor_ptr)(6, "Another arbitrary parameter");//память есть, явн овызываем конструктор.

Остальные методы надо вызывать также.
Деструктор надо вызывать так же и вручную!!!! Автоматом он не вызовется!!! (Ну если он конечно не виртуальный).

ЗЫ: вот классная дока по указателям на методы http://rsdn.ru/article/cpp/fastdelegate.xml?print
Записан
Icoz
Гость
« Ответ #23 : Июль 28, 2007, 17:55 »

Цитата: "Alex Forth"
Вызывать надо примерно так:
Код:

SomeClass *x = (SomeClass*)malloc( sizeof(SomeClass) );//new некатит т к компилер не может самостоятельно вызвать конструктор
(x->*my_constructor_ptr)(6, "Another arbitrary parameter");//память есть, явн овызываем конструктор.

Остальные методы надо вызывать также.
Деструктор надо вызывать так же и вручную!!!! Автоматом он не вызовется!!! (Ну если он конечно не виртуальный).

ЗЫ: вот классная дока по указателям на методы http://rsdn.ru/article/cpp/fastdelegate.xml?print

Дока классная! Только там не сказано, как указателю на фукцию преобразовать и присвоить значение void*?
Делаю так, не работет:
Код:

//typedef TMapAccess* (TMapAccess::*TMapAccess_ptr)(TMapAccess*);
//typedef void (TMapAccess::*TMapAccess_ptr)(TMapAccess*);
typedef void (TMapAccess::*TMapAccess_ptr)();
//typedef TMapAccess* (TMapAccess::*TMapAccess_ptr)();
...
TMapAccess* map = (TMapAccess*)malloc(sizeof(TMapAccess));
map->*TMapAccess_ptr(); // указатель на функцию-то не установлен!

Как установить указатель?
Так непашет:
Код:

TMapAccess_ptr = (TMapAccess_ptr)lib.resolve("@TMapAccess@$bctr$qv");

говорит, что ему нужна переменная, типа
TMapAccess_ptr - это ТИП.
Кароче, вопрос: как мне к этому указтелю прицепить resolve?

добавлено спустя 21 минуту:

 Судя по доке, должна работать такая вещь:
Код:

1: typedef void (TMapAccess::*TMapAccess_ptr)();
...
2: TMapAccess* map = new TMapAccess();
3: TMapAccess_ptr = &TMapAccess::TMapAccess;
4: map->*TMapAccess_ptr();

1 - объявляю указатель на функцию-член
2 - создаю объект
3 - присваиваю указателю значение (что он должен запускать)
4 - вызываю функцию-член по указателю
Есть НО! Не компилится. Матерится на 3-ю строку:
Код:

 error: expected primary-expression before '=' token
 error: expected primary-expression before ';' token

А по сути:
на второй строке должно быть просто выледение памяти, на третьей - присвоение указателю значения из lib.resolve();
Но я хочу хотя бы так скомпилить, чтобы синтаксис правильный был, а дальше будем усложнять...

добавлено спустя 16 минут:

 Сейчас делаю так(имхо, наиболее логично):
Код:

1: typedef void (TMapAccess::*TMapAccess_ptrTYPE)();
...
2: TMapAccess* map = (TMapAccess*)malloc(sizeof(TMapAccess));
3: TMapAccess_ptrTYPE TMapAccess_ptr = (TMapAccess_ptrTYPE)lib.resolve("@TMapAccess@$bctr$qv");
4: map->*TMapAccess_ptr();

Компилятор ругается:
Код:

3: error: cannot convert `(&lib)->QLibrary::resolve(((const char*)"@TMapAccess@$bctr$qv"))' from type `void*' to type `void (TMapAccess::*)()'
4: error: must use .* or ->* to call pointer-to-member function in `TMapAccess_ptr (...)'

Какие мысли есть?
Записан
Alex Forth
Гость
« Ответ #24 : Июль 28, 2007, 18:19 »

Каким компилером пользуешся?
Записан
Icoz
Гость
« Ответ #25 : Июль 28, 2007, 22:08 »

mingw в винде, разумеется. или тебе версия нужна?

добавлено спустя 32 секунды:

 mingw, который вместе с dev-cpp идет
Записан
Alex Forth
Гость
« Ответ #26 : Июль 28, 2007, 23:06 »

попробуй преобразовывать тип с помощью reinterpret_cast<>

Поверил, так тоже не выйдет. Простейший указатель на метод в gcc занимает 8 байт. Там должен быть адрес и еще что-то. Адрес ты резолвишь, а вот про оставшиеся 4 байта надо курить маны Улыбающийся
Записан
Icoz
Гость
« Ответ #27 : Июль 29, 2007, 16:52 »

Цитата: "Alex Forth"
попробуй преобразовывать тип с помощью reinterpret_cast<>

Поверил, так тоже не выйдет. Простейший указатель на метод в gcc занимает 8 байт. Там должен быть адрес и еще что-то. Адрес ты резолвишь, а вот про оставшиеся 4 байта надо курить маны Улыбающийся

Не понял. Подробнее.

добавлено спустя 2 часа 22 минуты:

 Слушай, у меня есть подозрение, что я гений!
Зачем мучаться с класами? По одиночке я же спокойно каждую функцию могу ресолвить? Только первым параметром надо добалять void* a_la_this. Размер класса я знаю, что мне мешает написать:
Код:

typedef void (*TMapAccess_constr_type)(void* map);
typedef int (*TMapAccess_OpenMap_type)(void* map, const char * mapname, int mode);
...
class TMyMapAccess: public QObject
{
Q_OBJECT
public:
TMyMapAccess(QObject * parent = 0);
...
private:
QLibrary lib;
void *map;// TMapAccess *map;
}

TMyMapAccess::TMyMapAccess(QObject * parent)
: QObject(parent)
{
lib.setFileName("mapacces");
lib.load();
map = malloc(129040 /*sizeof(TMapAccess)*/ );
TMapAccess_constr_type map_constr = (TMapAccess_constr_type)lib.resolve(TMapAccess_constr_type_str);
if (!map_constr) {
QMessageBox::critical(0,"TMyMapAccess error!","Can't load TMapAccess constructor!");
return;
}
map_constr(map);
}

int TMyMapAccess::OpenMap(const char * mapname, int mode)
{
TMapAccess_OpenMap_type map_OpenMap = (TMapAccess_OpenMap_type)lib.resolve(TMapAccess_OpenMap_type_str);
if (!map_OpenMap) {
QMessageBox::critical(0,"TMyMapAccess error!","Can't load TMapAccess constructor!");
}
return map_OpenMap(map,mapname,mode);
}


добавлено спустя 4 минуты:

 Получается, что я просто пишу простенькую оболочку для класса, используя только те функции, что мне нужны... Улыбающийся
Если поднапрячься, то вполне можно парсер написать, который мне по всем функциям пройдется и напишет шаблонный код! Улыбающийся
Только сначала надо будет руками по def-файлу пройтись. Грустный

добавлено спустя 2 минуты:

 ЗЫ. Самое прикольное, что просто передача дополнительного первого аргумента РАБОТАЕТ!!! Проверил пока 4 функции: конструктор, деструктор, OpenMap и CloseMap.

добавлено спустя 31 минуту:

 PPS. Отрисовка из dll на HDC работает на УРА! Улыбающийся Все! Я счастлив! Жизнь налаживается. Теперь будем делать это все красиво. Парсер буду писать(эх, ща буду Perl вспоминать)!
Alex Forth, с меня ПИВО! Улыбающийся Будешь в Москве - пиши в личку, втретимся - проставлюсь. Гут?

Тему, думаю, можно закрывать.

добавлено спустя 25 минут:

 PPPS. навсякий случай, чтобы сия ценная инфа не потерялась, запостил решение еще сюда:
http://www.rsdn.ru/Forum/message/1586925.flat.aspx
Записан
Alex Forth
Гость
« Ответ #28 : Июль 29, 2007, 20:01 »

Минут десять втыкал в приведенный выше код. Так до конца и не понял, почему он должен работать! Если ничего не глючит, то, скорее всего, тебе просто повезло. Дело в том, что (код привожу не совсем точный, главное общий смысл)
Код:

typedef void (*method_ptr)(void*, int);
method_ptr  myPtr = resolve("MyClasssomeMethod");
MyClass *instancePtr;
myPtr(instancePtr,1);//Внимание, ключевое место

и
Код:

MyClass instance;
instance.someMethod(1);//Внимание, ключевое место

соответствуют разному коду. В первом случае instancePtr - это обычный аргумент и он будет ложится в стек последним, перед вызовом функции. Во втором варианте, укахатель на экземпляр класса передается неявно ч-з регистр. Поидее в WIN, для совместимости с MSVC он должен перeдаваться ч-з ECX.

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

ИМХО Вывод: путем резолва заюзать класс из DLL можно. НО! Лично я, на практике пошел бы другим путем. Чего и тебе советую.

1 Вариант
Пиши свою DLL, которая юзает ту самую хитрую библиотеку классическим способом. При этом твоя библиотека предоставляет  нужный тебе интрфейс на основе виртуальных методов, которые замечательно позволяют загружать библиотеку динамически.

2 Вариант пишешь свое приложение с классической линковкой. Потом вручную выдираешь из екзешника фрагмент таблицы импорта. После это твой экзешник сможет  успешно грузится без той самой библиотеки. Ну и последний шаг, для этого варианта - это ручная загрузка DLL и ручное востановление затертого фрагметна таблицы импорта. Все это звучит страшно, но в формате виндового ЕХЕ ничего страшного нету.
Записан
Icoz
Гость
« Ответ #29 : Июль 29, 2007, 20:34 »

Цитата: "Alex Forth"

1 Вариант
Пиши свою DLL, которая юзает ту самую хитрую библиотеку классическим способом. При этом твоя библиотека предоставляет  нужный тебе интрфейс на основе виртуальных методов, которые замечательно позволяют загружать библиотеку динамически.

То есть ты мне предлагаешь вернуться к тому, с чего начали??? Я не хочу писать то, что уже написано. Да и зачем тогда это делать в библиотеке? Если уж напишу, то буду юзать сразу по месту требования.
Цитата: "Alex Forth"

2 Вариант пишешь свое приложение с классической линковкой. Потом вручную выдираешь из екзешника фрагмент таблицы импорта. После это твой экзешник сможет  успешно грузится без той самой библиотеки. Ну и последний шаг, для этого варианта - это ручная загрузка DLL и ручное востановление затертого фрагметна таблицы импорта. Все это звучит страшно, но в формате виндового ЕХЕ ничего страшного нету.

Че-то совсем стремно. Даже я со своим вариантом не настолько манов укурился. Улыбающийся Да и потом, как начальству объяснить, благодаря бубнам какой марки ЭТО работает?
Записан
Страниц: 1 [2] 3 4 ... 7   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.088 секунд. Запросов: 21.