Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Как передать массив в dll

9.2K
17 октября 2008 года
Ton
35 / / 13.10.2005
Дано:

type TCert = record
SubjName : PChar;
CertCTX : PCCERT_CONTEXT;
end;

В dll (написанной мною на Делфи) есть функция:
function Sample(var mas : array of TCert) : integer; export;

Как мне из программы ее вызвать и передать массив mas туда по ссылке чтобы он пришел в функцию dll корректно?
6
17 октября 2008 года
George
4.1K / / 05.01.2007
а втупую приходит некорректно?
a := Sample(mas);
9.2K
17 октября 2008 года
Ton
35 / / 13.10.2005
Неа, валяться ошибки сплошные. В теле программы массив можно посмотреть он будет иметь такой вид допустим:

mas[0].CertCTX = $160B15
mas[1].CertCTX = $160B15

а когда он с этими данными приходит в функцию Dll, там ваще какая то фигня типа:
{{mas[0].CertCTX = NULL } {mas[0].CertCTX = NULL}...}

Это ведь не нормально? соответственно когда я туда пробую писать чтото, то валятся ошибки... Решение я чувствую где то рядом и совсем простое..
6
17 октября 2008 года
George
4.1K / / 05.01.2007
ShareMem подключил?
9.2K
17 октября 2008 года
Ton
35 / / 13.10.2005
Подключил.
В упрощенном виде выглядит это так:

******Программа******************
type TCert = record
SubjName : PChar;
CertCTX : PCCERT_CONTEXT;
end;
PCCERT_CONTEXT = ^_CERT_CONTEXT

var mas : array of TCert;

procedure ...();
begin

SetLength(mas, 2);
Sample(mas); //Вызываем функцию из Dll

end;
**************************

В длл-ке: function Sample(var mas : array of TCert) : integer; export;

Что происходит: массив размером 2 уходит в dll с пустым содержимым. Как он приходит в dll я не знаю, просто Делфи начинает очень криво отображать если в AddWatch загнать mas. Далее массив заполняется и поидее возвращается программе.

Так вот я выяснил что перед выходом из процедуры Sample массив заполнен данными!
mas[0].SubjName = "testtest"
mas[0].CertCTX = "$1608B12"

и в программу приходит ПОЧТИ правильно!
mas[0].SubjName = "testtest"
mas[0].CertCTX = nil - но почему тут nil??
14
20 октября 2008 года
Phodopus
3.3K / / 19.06.2008
Попробуй сделать так:

Код:
PCCERT_CONTEXT = ^_CERT_CONTEXT;

type
  TCert = record
    SubjName : PChar;
    CertCTX : PCCERT_CONTEXT;
  end;

  TCertArray = array [0..65535] of TCert;
  PCertArray = ^TCertArray;

var pmas: PCertArray;

procedure ...();
begin
  GetMem(pmas, sizeof(TCert)*2);
  Sample(pmas, 2); //Вызываем функцию из Dll
end;


В длл-ке: function Sample(pmas: PCertArray; Items: Integer): integer; export;

А перед этим проверь, интерфейсная часть твоей записи объявлена лишь в одном модуле который используется как в dll-ке так и в программе?
9.2K
20 октября 2008 года
Ton
35 / / 13.10.2005
Неа, В Delphi 7 пробовал - там короче все едет в массивах и возвращается только один элемент корректно, но и то не туда попадает. В Delphi 2009 (под которым собственно пишу), вообще не захотел такой вариант компилить, я просидел 2 часа, но сплошные ошибки валяться.

Я честно скоро сойду с ума с этой задачей. Я уже неделю ее пишу и ни на шаг не продвинулся.

Проблема еще в том, что у меня на работе делфи 7, а дома - 2009. И код не совместим, как это не парадоксально. В 7-ке я сделал такой код который работает как надо, без ошибок после закрытия приложения. Но функцию я посадил в тело программы а не в dll. В 2009-ом тоже самое естественно не работает.

Я не знаю что делать... давайте начнем разговор с более общих вещей.
14
20 октября 2008 года
Phodopus
3.3K / / 19.06.2008
Код который я привел должен быть совместим across versions. Давай выкладывай компилирующийся пример
9.2K
20 октября 2008 года
Ton
35 / / 13.10.2005
Все подготовил, сформировал.

http://depositfiles.com/files/phyd25hxq

Вот инструкция что нужно сделать с архивом:
1. Установить сертификаты из папки "Сертификаты". Запускаем каждый *.cer, на первой закладке кнопка "установить сертификат". Появляется окно, нажимаем "далее". Выбираем "Поместить все сертификаты в следующее хранилище". Обзор. Должен быть выбран пункт "Личные". ОК. Далее. Готово. Так оба сертификата

2. Посмотреть сертификаты можно если набрать в выполнить: certmgr.msc
Самая верхняя папка - "личные" Вот их мы и должны получить в программе

3. В папке win32api - все модули какие тока может запросить делфи. Самые важные уже лежат в одной папке с проектом(wcrypt.pas, jwa*.pas).

4. Приложение - Project1. dpr
5. Библиотека - XCryptoLib.dpr

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

PS: буду очень благодарен если кто поможет :) обещаю бесплатно выслать продукт над которым сейчас работаю, бета которого намечена на декабрь 2008.
14
21 октября 2008 года
Phodopus
3.3K / / 19.06.2008
Ну я только лишь "слегка" взглянул и сразу увидел классическую ошибку которую ты допустил: разделяемая между приложением и библиотекой структура объявлена 2 раза - и там, и там. И естественно эти объявления отличаются. Запомни: когда пишешь приложение предоставляющее или использующее внешний интерфейс (будь то плагин или один проект на несколько человек) - интерфейсные модули должны быть вынесены отдельно и использоваться каждым "куском" приложения - они должны быть разделяемы между кусками. Все эти объявления экспортируемых функций, разделяемых структур и т. д. должны быть в отдельном модуле, который будет использовать и библиотека и программа.
9.2K
21 октября 2008 года
Ton
35 / / 13.10.2005
Ёма-Народ!! Работает! Phodopus слов нет ) знаешь когда вот так запаришься неделю в отладке, такую простую вещь и не заметил я!

Решение проблемы (для тех у такая же проблема была):
Вынес описание структуры TCert и описания функций dll которые раньше в программе лежали в отдельный *.pas файл, подключил его в uses в библиотеке и в проге самой

Phodopus говори e-mail, и ФИО свое. С меня причитается ;-)

PS: у меня кстати новый вопрос, почему нельзя при загрузки программы загрузить dll динамически, а дальше исользовать ее функции в теле программы на всем протяжении ее работы. А потом при закрытии программы освободить память и выгрузить библиотеку? Выдает ошибку access violation
6
22 октября 2008 года
George
4.1K / / 05.01.2007
Почему нельзя? Можно? ТОлько если ты хочешь грузить библиотеку при загрузке программы, а выгружать при закрытии программы, не проще ли подключать длл статически?
но если надо обязательно динамически, то гони код загрузки и код выгрузки. :)
9.2K
22 октября 2008 года
Ton
35 / / 13.10.2005
Загружаю динамически на случай если рядом не будет библиотеки, чтобы ошибка не вылетала. Хотя может и правда стоит задуматься на счет статики. Сейчас же ошибка вылетает как только я пытаюсь вызвать функцию которую загрузил из длл не сейчас, а при старте программы.

Объявления в разделе interface:
 
Код:
var
  frmMain: TfrmMain;
  hndDLLHandle: THandle;
  DFunc: TDFunc;

type
  TDFunc = procedure (par1 : DWord; par2 : DWORD);


Загрузка:
Код:
procedure TfrmMain.FormCreate(Sender: TObject);
begin

  try
    hndDLLHandle := loadLibrary ( 'Mylib.dll' );

    if hndDLLHandle <> 0 then
    begin
      @DFunc := getProcAddress (hndDLLHandle, 'DFunc');
    end;

    exit;

  finally
    freeLibrary ( hndDLLHandle );
  end;
end;


Выгрузка:
 
Код:
procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
   freeLibrary ( hndDLLHandle );
end;
6
22 октября 2008 года
George
4.1K / / 05.01.2007
у тебя в коде загрузки библиотеки надо убрать строку FreeLibrary(hndDLLHandle); потому что получается что ты при загрузке проги грузишь библиотеку, вызваешь из нее функцию и выгружаешь сразу, а при завершении программы ты опять пытаешься выгрузить библиотеку, которая уже выгружена. посему и ошибка. :) да и exit убери. и конструкцию try finally end;

[highlight=delphi]
procedure TfrmMain.FormCreate(Sender: TObject);
begin
hndDLLHandle := loadLibrary( 'Mylib.dll' );
if hndDLLHandle <> 0 then
begin
@DFunc := getProcAddress (hndDLLHandle, 'DFunc');
end;
end;[/highlight]
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог