Сложный технический вопрос по DLL - как передавать указатели на объекты? - страница 2

 
Если есть желание конструктивно поговорить, выкладывайте что передаете и как принимаете в ДЛЛ (без лишнего). А так гадать долго можно.
 
TheXpert:

size_t это тот же unsigned, размер как у инта ) а DWORD_PTR это дефайн, который тип указателя на тот же unsigned, которого в MQL ессно нету. В итоге как всегда из попытки выпендриться получается клоунада )

А насчет указателей правильно, лучше дескриптор передавать, а указатель держать у себя в укромном месте и брать по дескриптору когда надо.

Прямой ответ на прямой вопрос -- на 64х инта не хватит.

Вот специально цитирую для истории.

Андрей, думал раньше, что ты программист... :-( Тебе ещё много чего придётся узнать... Хотя бы заглянул в студию, прежде, чем фигню написать.

Строки 421, 422 BaseTsd.h:
typedef ULONG_PTR SIZE_T, *PSIZE_T;
typedef LONG_PTR SSIZE_T, *PSSIZE_T;
Строка 476 BaseTsd.h:
typedef ULONG_PTR DWORD_PTR, *PDWORD_PTR;

Что, дефайн от синонима пока ещё не отличаешь?

Дальше, надеюсь, квалификации хватит разобраться, что это (строки 125-143 BaseTsd.h) ?

#if defined(_WIN64)
    typedef __int64 INT_PTR, *PINT_PTR;
    typedef unsigned __int64 UINT_PTR, *PUINT_PTR;

    typedef __int64 LONG_PTR, *PLONG_PTR;
    typedef unsigned __int64 ULONG_PTR, *PULONG_PTR;

    #define __int3264   __int64

#else
    typedef _W64 int INT_PTR, *PINT_PTR;
    typedef _W64 unsigned int UINT_PTR, *PUINT_PTR;

    typedef _W64 long LONG_PTR, *PLONG_PTR;
    typedef _W64 unsigned long ULONG_PTR, *PULONG_PTR;

    #define __int3264   __int32

#endif

Строки 26-30 sourceannotations.h

#ifdef  _WIN64
typedef unsigned __int64    size_t;
#else
typedef _W64 unsigned int   size_t;
#endif
Видишь ли, это такая конструкция, которая меняет размер типа в зависимости от разрядности проекта.

И синглетон у тебя фуфло :-) Уровень абстракции зашкаливает не в ту сторону.

 
CanSee:


Спасибо за советы :)

Начнём по пунктам.

0. Я конечно понимаю, что фигню придумывать не надо :) Но придётся, если не получится сделать по уму :) Если не через строку - значит, как-то ещё. Если не получится - придётся оставлять так как есть (через инт). Это не лучший вариант, но по крайней мере он в большинстве случаев работает.

1. Я вообще думал, что MetaTrader 4 является 32-битным и в 64-разрядных ОС работает внутри виртуальной машины, которая делает для него соответствующие указатели. Потому и надеялся, что инты сгодятся. DLL тоже 32-битная.

2. Что там использовать внутри DLL - это не проблема.Там я могу использовать что угодно. Проблема в том, как это что-то передать наружу.

3. А вот это самый важный вопрос. Так сделать - наверное, это было бы лучше всего. Но каким образом можно так сделать? Я пока что не догадался.

Вот у меня есть база данных. Есть робот на MQL4. И есть DLL. Робот в начале своей работы хочет подключиться к БД. Он вызывает функцию подключения, которая возвращает указатель на полученный объект подключения. При вызове следующих функций, которые работают с подключением, им надо передать указатель на этот объект. Каким образом можно обойтись без того, чтобы передавать роботу из DLL полученный указатель, а затем передавать его обратно из робота в функции? Если не передавать его роботу - где его тогда хранить? У меня пока что нет идей, где внутри DLL можно было бы хранить указатель на созданный объект. Можете ли вы что-нибудь посоветовать? Я был бы очень благодарен.

0. Точно не надо!

1. Конечно, если 32 разрядная, то и указатели соответствующие. Но для возможности автоматической компиляции под текущую разрядность надо использовать специальные типы. Просто в первом посте Вы сказали что-то про 64 разрядные ОС. Подумал, что Вам, как-то удалось передать данные из 32 в 64, а DLL у Вас мост между Вашей 64-разрядной базой и 32-разрядным терминалом. Вполне это через маппинг получится.

2-3. Напишите конкретно, что там передаёте. Лучше код. Так понятнее будет.

Всё же, из БД нужны какие-то данные, а не указатели? Может протокол общения нарисуете?

 
Zhunko:

Андрей, думал раньше, что ты программист...

Ну думай что ты меня макнул ) если тебе так легче .
 
220Volt:


Тогда никаких проблем. А вот так адрес не передается?

Таким образом не пробовал. Посмотрел в учебнике - но там было написано только о передаче таким способом int по ссылке, а про указатели ничего не говорилось. Я долго раздумывал, подойдёт ли это для передачи указателя, но в коде реализовать не пробовал. Теперь думаю по совету TheXpert попробовать вообще обойтись без указателей :)

 
220Volt:
Если есть желание конструктивно поговорить, выкладывайте что передаете и как принимаете в ДЛЛ (без лишнего). А так гадать долго можно.

Ну, в общем-то, код показать всегда лучше, хотя он и кривоват :) Я решил пробовать без указателей (через хранение их в статических переменных), но проблемный код всё же приведу.

Сначала объяснение, как оно работает. Используется Qt 4. В DLL объявлены экспортируемые функции - те, которые будут вызываться из MQL4. Также описан класс, который отвечает за работу с БД. Назначение класса простое - по запросу от робота открывает соединение с БД и сохраняет его во внутренней переменной, а функция возвращает указатель на созданный объект этого класса роботу. Потом другая функция принимает от робота этот указатель и данные, которые роботу надо в базу записать. Все данные передаются параметрами фу6кций с простыми типами - int, double, string, больше ничего. При завершении работы вызывается функция деинициализации, которая вызывает в классе функцию закрытия соединения и затем освобождает объект класса. Чтение данных из БД внутри робота не производится (планируется в будущих версиях по той же схеме). Вот с передачей указателя возникла проблема. Вернее, я думаю, что проблема с передачей указателя. Но на самом деле она может быть и в чем-то другом.

Функция инициализации - создаёт объект класса MqlDll (который работает с БД), открывает соединение через вызов функции класса и возвращает ссылку на класс, преобразованную в int, роботу:

MT4_EXPFUNC int __stdcall OpenConnMySql(char* sConnNameIn, char* sHostNameIn, int iPortIn, char* sDbNameIn, char* sUserIn, char* sPassIn)
{
// Создаём объект MqlDll:
MqlDll * dllClass = new MqlDll();
// Пробуем открыть соединение с MySql:
dllClass->openMySqlDb(QString(sConnNameIn), QString(sHostNameIn), iPortIn, QString(sDbNameIn), QString(sUserIn), QString(sPassIn));
// Возвращаем ссылку на полученный класс:
return (int)dllClass;

}

Описание этой функции в роботе на MQL4:

int OpenConnMySql(string sConnNameIn, string sHostNameIn, int iPortIn, string sDbNameIn, string sUserIn, string sPassIn);

Функция деинициализации (закрытие соединения выполняется в деструкторе класса):

MT4_EXPFUNC void __stdcall CloseConnection(const int iPointer)
{
MqlDll * dllClass = (MqlDll *)iPointer;
delete dllClass;

}

Описание этой функции в роботе на MQL4. Полученный от функции инициализации указатель робот передаёт в функцию, как int:

void CloseConnection(int iPointer);

Ну и для примера одна из функций, работающих с указателем. Служит для получения от класса описания последней ошибки, произошедшей при работе с БД:

MT4_EXPFUNC char* __stdcall GetErrorMsg(const int iPointer)
{
// Преобразуем переданный int в указатель на класс:
MqlDll * dllClass = (MqlDll *)iPointer;
// Вызываем функцию получения описания последней ошибки:
return dllClass->getErrorMsg().toLatin1().data();
}

Описание на MQL4:

string GetErrorMsg(int iPointer);

Вот примерно так оно всё и работало.

 
Кстати советую сразу делать под новый билд с новым языком, там строки широкие, все равно переделывать, а обновление скоро.
 
TheXpert:
Кстати советую сразу делать под новый билд с новым языком, там строки широкие, все равно переделывать, а обновление скоро.

А что это за новый язык? MQL5? Если да - то не получится. Заказчик работает с MQL4. Поэтому надо делать именно на четвертом. Пятый для него не годится из-за особенностей 5 терминала, а именно из-за усреднения ордеров. У него бывает целая куча позиций по одному инструменту, часть из которых разнонаправленные. В пятом терминале они все сложатся в одну.

В будущем планирую сделать также версию для 5 МТ. Но сначала надо довести до ума саму DLL, и сделать версию для МТ4.

 
Zhunko:

И синглетон у тебя фуфло :-) Уровень абстракции зашкаливает не в ту сторону.

Это как? фонит что ли? ) ну покажи свой православный для тех же задач )