Как из dll получить массив

Обновлено: 07.07.2024

Репутация: нет
Всего: нет

Я пишу DLL с единственной функцией, которая будет использоваться в JAVA коде через JNI.

Как ее правильно определить чтобы она возвращала массив строк?

Сейчас выглядит так:

И как заполнять выходной массив?

Нужно ли будет освобождать память под выделенные строки?

Репутация: нет
Всего: нет

Так. Немного освежил память.

Допустим если запихнуть строки в область памяти разделенную 0 байтами и в параметре length вернуть размер област?
Будет ли это работать?

Добавлено через 4 минуты и 24 секунды
Омг. Еще момент. Какой тип строк использовать? wchar_t это utf-8? Т.е. я могу вставить нулевой байт и это будет рассматриваться как конец строки?

Хз вобщем посоветуйте плз как бы вы в это ситуации себя вели?

Репутация: 2
Всего: 23

v00d00, если память выделяется в DLL то и освобождатся она должна
в ней же - нужнв функция для освобождения ресурсов Вообщем, как-то так - могут быть ошибки с количеством звёздочек и выплывающие с этогопроблеммы

Репутация: нет
Всего: нет

А как уловить момент когда стоит освободить память?

У Dll в винде есть callback для обработки завершения вызова процедуры?

Добавлено через 2 минуты и 40 секунд
Зло. Как же я затупил.
Как мне записать массив байт в стек?

Добавлено через 11 минут и 13 секунд
если я объявлю в начала процедуры такой массив

и запишу туда посимвольно данные из контейнерного класса (CStringList) и верну

Будет ли это кривым решением?

Репутация: нет
Всего: нет

Блин. как же правильно определить прототип функции? Голова взрывается уже.
Dll выполняется в одном и том же адресном пространстве что и наша прога. Т.е пользователь ответственен за освобождение памяти.

Другой вопрос. Будет ли это работать с JAVA?

Репутация: 53
Всего: 183

Мне кажется, для такого рода меж-языкового общения безопаснее всего использовать SAFEARRAY + BSTR: их выделением занимается система, есть набор функций для обработки, так что проблем с памятью быть не должно. Кроме того, эти типы разработаны специально для подержки Automation, т.е. должны в том или ином виде поддерживаться всеми языками.

Репутация: 1
Всего: 23

v00d00, а STL использовать можете? При возврате контейнера произойдет его копирование. То, что выделилось в DLL, освободится нужным delete.

Репутация: 53
Всего: 183

Репутация: 15
Всего: 118

как я бегло понял в JNI есть поддержка Callback-ов, почему бы для заполнения родных для Java контейнеров не воспользоваться ими? (передавать по одной простой (простой с т.з. структуры данных) строке в callback)
Что-то не поняли? -> Напейтесь до зеленых человечков. эта сверхцивилизация Вам поможет.
  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это! хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

[ Время генерации скрипта: 0.1644 ] [ Использовано запросов: 21 ] [ GZIP включён ]

идея такова.В своем приложении я вызываю библиотеку,которая заполняет данный массив до некоторого размера. В основном приложении я хотел бы получить его длину и,соответственно,все данные.
Но вот не получается с кодом :(

ps Почему GlobalLock вызываешь два раза, а GlobalUnlock - только один??

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

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

EXE вызывает функцию вначале с nil-указателем, получая необходимую длину буфера, выделяет буфер и вызывает функцию снова -- с указателем на готовый буфер.

Или использовать IMalloc или функции-оболочки вокруг его системной реализации CoTaskMemAlloc etc

Или делать COM-сервер и реализовать интерфейс-перечислитель.

Или использовать IMardhal и реализовать объект, передаваемый "по значению".

И все эти способы, как и [2], дают большую или меньшую незаисимость от среды разработки.

Данный код работает ;)

>вообще мне не нравится твой подход
А я и не говорил,что это мой подход! Это подход Тенцера.Взято у него в книге. Также автор предлагает использовать ф-цию CoTaskMemAlloc указанную в [4].

>Или ты представляешь как они работают?
Представляю.

> тогда, объясни мне пожалуйста - почему твой код не вызывает av?
А с чего он должен вызывать AV. Был пример в книге. Сперва я попробовал передавать Integer и структуру. все получилось. Ну,а потом массив. А проблемы возникали из-за указателей.

>Советую в казино сходить, с таким везением имеешь все шансы Джек Пот сорвать.

Этот термин имеет прямое отношение к данному типу.
Мы не в Паскале, а в Делфи!
Открытый масив записей!
Открытый масив применимо к объявлению "array of . ".
Хотя нет такого типа(. )! Дык по этому и говорят просто "открытый масив"
с динамическим распределением памяти. Суть дела не меняется!
Чел. взял да и сделал двойной указатель, потом при помощи
вызова GetMem выделил под вторичный указатель памяти до][. на.
Ну, так нельзя! Дельфя то ругаться не будет, но и работоспособности это
не прибавит!

. Для dll и EXE память всегда неразделяемая .
Еще раз прочитай первую строчку поста, и улыбнись.

Нифчего подобного! Для подтверждения моих слов делаем такую вещь:
Открываем Делфи.
Выбираем "Создать-Мастер DLL".
Смотрим и внимательно, со словарем(если без словаря не получается),
Читаем то, что дядя Борланд там написал в коментариях.

А это так, от меня, воспоминания.
При загрузке программы для нее создается страница адресного
пространства требуемого размера. Далее, если программа использует
внешние исполняемые библиотеки, то их код загружается однократно.
Впринципе, как код и самой программы. Далее создаются страницы
адресного пространства для исполняемых библиотек. API Windows
тоже имеют свое адресное пространство, и загружаются в ОП
однократно, далее используются только из ОП.

А как можно разделить, где мое пространство, а где моей DLL-ки?
Только с помощью менеджера памяти! Иначе Программа просто
не сможет оперировать адресами из области DLL.

И чем же вредный? Если есть иной (менее вредный) выход (а он, судя по комментарию, есть) - выкладывай, возьму на заметку . Посоветовал то, что сам использую. Конечно есть out, но это не выход. (в смысле, из положения )

Насчет поста о комментарии в DLL - я тоже ничего не понял. Там, кажись, написано о строках, а не динамических массивах. ИМХО все из-за совместимости dll для разных языков программирования. И ТС использует PChar, String нигде нет.

В алгоритме, который привёл автор топика, в DLL передаётся указатель на уже выделенную память, в DLL она только заполняется. Поэтому лишний var тут не нужен. Var может понадобится в случае, когда передаётся структура и в DLL она будет изменена. Посмотрите модуль windows.pas. Во многих случаях, когда в API функции требуется указатель на переменную или структуру, в паскале используется синтаксис в var. А когда нужен массив - используются указатели.

По поводу комментария - механизм работы со строками и динамическими массивами один и тот же.

Спасибо за информацию.

Сейчас вычисления в DLL проходят нормально и результаты я использую в основной программе, но при закрытии программы вылетает ошибка чтения памяти. Может надо какой ресурс очистить?

Это общий класс DLL и основной программы

механизм работы со строками и динамическими массивами один и тот же

Ну, если так, то сделай следующее: Обьяви динамический массив размером 5 и строку длиной 5 символов, затем попробуй обратится к массив[5] элементу и строка[5] элементу, а также массив[0] элементу и строка[0] элементу - скажи что получилось. И как dll должна реагировать на 0 элемент строки. Как я уже писал, в разных языках программирования (отчасти Delphi и C) строки отличаются друг от друга, и в С строка оканчивается на NULL(для признака последнего символа), в Delphi же в 0 индексе содержится информация о длне строки. Так что эта заметка к динамическим массивам отношения не имеет.

to Сергей77 А если запускать не из среды программирования, вылеты тоже наблюдаются?

Допустим вот такая простая структура, зато в которой и строка и число есть:

Во-вторых, тебе нужно, чтобы для выделения и освобождения использовался один и тот же менеджер памяти. Это можно сделать несколькими путями, например:

- подключить в DLL дельфовые функции GetMem/FreeMem
- использовать для выделения и освобождения функции Win API
- по завершении работы со структурой передать ее функции "освободить", также расположенной в DLL.

Последний путь - пожалуй, наиболее правильный.

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

> И начать очередную серию идиотских проблем вида "в нашей системе имя
> может быть максимум 20 символов"?
>
По-моему, лучше тогда будет, если эти структуры будут жить внутри
библиотеки, и создавасться/уничтожаться ей же. Т.е. мендежеры памяти
будут раздельные.

Posted via ActualForum NNTP Server 1.4

> Но в целом тут вопрос. Имхо, правильный ответ зависит от архитектуры
> решения в целом. Если это "маленький плагин к большой системе", то
> пусть он лучше будет замкнутым и самодостаточным. А если система в
> целом плагинная, лучше опубликовать общее API в том числе менеджера
> памяти.
>
Логично, полностью согласен.
Я просто исходил из предположения, что система небольшая.(например,
дельфийские GUI/C++ движок для небольшого приложения)

Posted via ActualForum NNTP Server 1.4

Posted via ActualForum NNTP Server 1.4

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

> Я ж именно про это и говорил?
Пардон. Прочел первую фразу, развил идею, в результате получилось то же
самое :).

Читайте также: