Получение строк из dll

 

Пишу dll, из которой надо перегонять строки в MQL (NULL-terminated ANSI).

Понятно, что существует способ в стиле WinAPI: в один запрос спросить у dll требуемую длину строки, потом подготовить приёмный буфер достаточной длины, и во второй запрос попросить dll скопировать строку в этот буфер.

Но:

- очень уж кривенький способ - изящество отсутствует напрочь;

- performance hit: сначала сформировать строку в dll, потом скопировать, потом сконвертировать в UNICODE на стороне MQL;

Кроме того, случай у меня особый: некоторые строки вообще являются константами, ну а время жизни остальных явно контролируется вызовами функций dll.

Собственно вопрос: можно ли в MQL всё же получить указатель на массив char'ов? Перепробовал массу вариантов - везде уткнулся в забор.

 
Alexander Dubovik:

Пишу dll, из которой надо перегонять строки в MQL (NULL-terminated ANSI).

Понятно, что существует способ в стиле WinAPI: в один запрос спросить у dll требуемую длину строки, потом подготовить приёмный буфер достаточной длины, и во второй запрос попросить dll скопировать строку в этот буфер.

Но:

- очень уж кривенький способ - изящество отсутствует напрочь;

- performance hit: сначала сформировать строку в dll, потом скопировать, потом сконвертировать в UNICODE на стороне MQL;

Кроме того, случай у меня особый: некоторые строки вообще являются константами, ну а время жизни остальных явно контролируется вызовами функций dll.

Собственно вопрос: можно ли в MQL всё же получить указатель на массив char'ов? Перепробовал массу вариантов - везде уткнулся в забор.

конечно нельзя из DLL возвращать указатель на её делелелину память :-) даже просто из общих принципов

но если строки константные, может вам и гонять туда-сюда константы ? ulong ~ 2^64 это офигительная величина..

---

ps/ вы уверены что указанное в топике является bottle-neck ? есть шанс впасть в "грех преждевременной оптимизации"

 
Maxim Kuznetsov:

конечно нельзя из DLL возвращать указатель на её делелелину память :-) даже просто из общих принципов

но если строки константные, может вам и гонять туда-сюда константы ? ulong ~ 2^64 это офигительная величина..

---

ps/ вы уверены что указанное в топике является bottle-neck ? есть шанс впасть в "грех преждевременной оптимизации"


В данном случае я могу гарантировать, что аллоцированная в памяти dll строка будет там оставаться достаточно долго (некоторые - до моей команды на её удаление, а константы так вообще до выгрузки dll). Других соображений о невозможности доступа к памяти dllя не знаю (хотя опыт с dll у меня может и не достаточен).

ulong мне определённо не достаточно, т.к. надо гонять не-константные строки порядка десятков килобайт.

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


Итого: вопрос у меня больше о синтаксисе MQL.

string  CharArrayToString(
   uchar   array[],             // массив
   int     start=0,             // начальная позиция в массиве
   int     count=-1,            // количество символов
   uint    codepage=CP_ACP      // кодовая страница
   );


Вот как бы так заборы обойти, и всё же получить переменную, подходящую на роль ссылки (указателя) на массив чаров?

 
Alexander Dubovik:


В данном случае я могу гарантировать, что аллоцированная в памяти dll строка будет там оставаться достаточно долго (некоторые - до моей команды на её удаление, а константы так вообще до выгрузки dll). Других соображений о невозможности доступа к памяти dllя не знаю (хотя опыт с dll у меня может и не достаточен).

ulong мне определённо не достаточно, т.к. надо гонять не-константные строки порядка десятков килобайт.

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


Итого: вопрос у меня больше о синтаксисе MQL.

string  CharArrayToString(
   uchar   array[],             // массив
   int     start=0,             // начальная позиция в массиве
   int     count=-1,            // количество символов
   uint    codepage=CP_ACP      // кодовая страница
   );


Вот как бы так заборы обойти, и всё же получить переменную, подходящую на роль ссылки (указателя) на массив чаров?

легально, сиречь не разрушительно для терминала - никак. Платформа со строками оперируем своими методами. В приниципе можно протелепатить как именно (вариантов немного на самом деле), и даже подсунуть данные и оно даже сработает в конкретном билде.
Но только эти усилия того не стоят.
Мы же про деньги в итоге ? деньги любят гарантрии, оф. API - гарантирован.

(как-то тоже кое-чего писал и очень сомневался что в MT - строки UTF16 а в транспорте UTF8 и надо перегонять туда-сюда..в конечном итоге затыка оказалась в стороннем JSON-парсере, вот он реально ЖРАЛ)
 
Maxim Kuznetsov:

конечно нельзя из DLL возвращать указатель на её делелелину память :-) даже просто из общих принципов

Интересный вопрос. Вроде бы и действительно нельзя, в МКЛ нет указателей, есть некий эрзац.

В тоже время, недавно смотрел материалы по подключению к МКЛ SQLite.dll. И для этого кроме самой SQLite.dll нужен только mqh файл. Но БД надо ведь сначала подключить, и ссылку на нее отправить в МКЛ, и уж потом через эту ссылку вызывать функциональность БД.

Подробно не разбирался, не было надобности. Просто удивился. Типа, как это?

 
Yuriy Asaulenko:

Интересный вопрос. Вроде бы и действительно нельзя, в МКЛ нет указателей, есть некий эрзац.

В тоже время, недавно смотрел материалы по подключению к МКЛ SQLite.dll. И для этого кроме самой SQLite.dll нужен только mqh файл. Но БД надо ведь сначала подключить, и ссылку на нее отправить в МКЛ.

Подробно не разбирался, не было надобности. Просто удивился. Типа, как это?

отдаёшь из DLL наверх ссылку (void *) как uint соотв. размерности (32/64) и всё щастье.

то есть некая функция DLL:

// С code
MyStruct *init_descriptor() {

    return malloc(sizeof(MyStruct));

}

получается в прототипах MQL как :

// MQL code
unsigned long init_descriptor();

 
Maxim Kuznetsov:
легально, сиречь не разрушительно для терминала - никак. Платформа со строками оперируем своими методами.

Не-не-не, во внутреннее представления MQL string лезть я не собираюсь.

Именно для объяснения своих намерений я и привёл объявление CharArrayToString из документации (в документации, кстати, там "&" потеряли у первого аргумента, а в подсказке MetaEditor всё правильно). Я планирую скормить CharArrayToString указатель (ссылку) на NULL-terminated ANSI-строку, которую получу из dll.

Сейчас на форуме вот такой синтаксис выискал:

type* &name[];

Завтра буду пробовать эту чудную конструкцию.

 
Maxim Kuznetsov:

получается в прототипах MQL как :

// MQL code
unsigned long init_descriptor();

И что, конструкция типа

// MQL code
unsigned long init_descriptor();


unsigned long a=init_descriptor();

a.func(x,y); //при описание в хидерфайле, разумеется

скомпилируется и будет работать?

 
Alexander Dubovik:
вы можете передавать указатель на массив и его размер.
 
TheXpert:
вы можете передавать указатель на массив и его размер.

Это как бы и приводит к WinAPI-style. Размер строки ведь заранее я не знаю.

 
Yuriy Asaulenko:

И что, конструкция типа

скомпилируется и будет работать?

во так вот напрямую как

unsigned long a=init_descriptor();

a.func(x,y); //при описание в хидерфайле, разумеется

конечно же нет . Но везде (и всегда, и даже помимо MQL) делается обвязка чтобы в конечном итоге вызвать

func(a,x,y); // вместо a.func(x,y)

---

по живому и любимому:

у меня есть библиотека ATcl . в ней единственный класс ATcl который предоставляет интерпретатор tcl для MQL скриптов.
Но у него внутри в полях, фактически единственный uint (ulong) который по сути указатель который получен из DLL.

Пользователь MQL привычными образом общается с инстанцами  класса, а этот класс переводит вызовы к DLL.

код всей  "оплётки" он в принципе однотипный..

Причина обращения: