Тема: Как импортировать функцию из dll в Pascal?

Проблема возникла при разработке инсталлятора на Inno Setup.
Написал на VB и скомпилировал в dll-файл программку прединсталляционной проверки: PreCheck.dll, где в модуле класса объявлена функция:

Public Property Get CheckValue() As Boolean
-----------------------------------------------------
--------------------------------------------------
End Property

Затем в секции Code поместил вызов этой функции. Не будучи знаком c языком Pascal, аккуратно (как мне кажется) срисовал
все это дело с книги "САПР на базе AutoCAD...":

function CheckValue():boolean;
external 'CheckValue@files:PreCheck.dll';
function InitializeSetup(): Boolean;
begin
 if CheckValue then
    Result := True
 else
    Result := False
 end;

При этом сам dll-файл включил в инсталляцию, исключив его установку на пользовательскую машину:

[Files]
Source: PreCheck.dll; Flags: dontcopy

Успешно скомпилировал исходник инсталлятора в исполняемый файл дистрибутива, однако при попытке его запустить получил сообщение об ошибке:
Runtime Error(at-1:0);
Cannot import dll:C:\....\PreCheck.dll - адрес несуществующей директории, где этого файла сроду "не стояло".
Подскажите, пожалуйста, где искать, куда копать?
Спасибо.

Re: Как импортировать функцию из dll в Pascal?

Обрати внимание:
1.

function CheckValue():boolean;
external 'CheckValue@files:PreCheck.dll  [b]stdcall[/b]';

2. Просто проще

function InitializeSetup(): Boolean;
begin
 Result := CheckValue;
end;

3.Добавь путь относительно скрипта

Source: PATH\PreCheck.dll; Flags: dontcopy

Это возможные места ошибок на уровне Inno. Все остальное - ошибка самой DLL. Так ли написана, тот ли тип данных возвращает и прочее.

Re: Как импортировать функцию из dll в Pascal?

А что значит "путь относительно скрипта"? Место файла в дистрибутиве или как?..
Ведь он прописан в секции: Files, и как я понимаю, при компиляции включается в дистрибутив.
Добавление служебного слова stdcall не помогло, может быть дело в некоей несовместимости языков программирования - VB vs PASCAL? Какой-то другой механизм вызова? Но ведь DLL для того и создаются, чтобы быть использованными РАЗЛИЧНЫМИ программами...
Моя DLL в порядке, протестировал ее в качестве COM-сервера.

Re: Как импортировать функцию из dll в Pascal?

1. Путь относительно скрипта - чтобы файл попал в дистрибутив. Если просто
Source: PreCheck.dll
то эта dll должна быть в одной папек со скриптом. Может быть и так. Просто это возможное место ошибки.
2. COM-сервер здесь не причем. Это должна быть обычная dll. Для совместимости в самой dll в определении функции также должна быть директива stdcall. Как это на VB делается я не знаю. Раньше на VB вообще нельзя было dll сделать, теперь наверное можно.
На Pascal такую dll можно написать так

library PreCheck;
uses ....
function CheckValue() : boolean; [b]stdcall[/b];
begin
//Тут код, возвращающий результат
Result:=....
end;
// Обязательно объявление экспортируемых функций
[b]exports[/b]
  CheckValue;
begin
end.

На всякий случай проверить надо, что в VB считается истиной/ложью. Может быть и 1/0.

Re: Как импортировать функцию из dll в Pascal?

Кстати, каталог, где "сроду не стояло" - это какой-нибудь каталог для временных файлов. Inno туда распакует dll (dontcopy) - иначе как же ее выполнить? Потом она будет удалена, а в каталог программы не будет копироваться.

Re: Как импортировать функцию из dll в Pascal?

> ShaggyDoc
Спасибо, вы помогли мне разобраться в ситуации.
В итоге, я нашел во встроенном в Inno Setup Pascal'е функции для работы с  Visual Basic ActiveX DLL:

function CreateOleObject(const ClassName: string): Variant;
function GetActiveOleObject(const ClassName: string): Variant;
procedure CoFreeUnusedLibraries;

Правда, когда попытался их использовать, снова
застрял:

{ Create PreCheck COM Automation object }
{-------------PreInnstallCheck------------------}
const
  ServerName = 'Class_PreCheck';//имя класса
function InitializeSetup(): Boolean;
var
  VB_Server: Variant;
begin
   VB_Server := CreateOleObject(ServerName);
   Result := VB_Server.CheckValue;
end;

Код компилируется, но при запуске возникает ошибка:
Runtime Error (at 1:55);
Invalid class string
Впечатление такое, что не проходит имя сервера.
В принципе, у встроенного Pascal немало возможностей, и мою проверку да и многое другое можно просто прописать в секции Code.
Но жаль, если не смогу воспользоваться привычным для меня Visual Basic 6.0.

Re: Как импортировать функцию из dll в Pascal?

> LeonidSN
В данном случае просто этот COM-сервер не зарегистрирован. Он же "временный". Значит надо его установить, зарегистрировать, поработать, разрегистрировать и удалить.
Что, действительно в VB нельзя сделать обычную dll? Кстати, не факт что на машине у пользователя окажется и run-time система для VB.

Re: Как импортировать функцию из dll в Pascal?

Нашел, наконец, ошибку в своем коде.
Пусть умные учатся (на чужих ошибках).
При вызове компонента надо было указать: "Имя_проекта.Имя_класса":

const
  ServerName = '[b]PreCheck.[/b]Class_PreCheck';
function InitializeSetup(): Boolean;
var
  VB_Server: Variant;
begin
   VB_Server := CreateOleObject(ServerName);
   Result := VB_Server.CheckValue;
   if Result then
   MsgBox('You fine fellow, Leonid!', mbInformation, mb_Ok);
end;

Что касается невозможности создания обычных dll в VB6, то да - в "классическом VB6" это невозможно. Но я слыхал что-то про PowerBasic, там вроде бы возможно. Сам я не разбирался и не проверял.

Re: Как импортировать функцию из dll в Pascal?

К вопросу об обычных dll и Visual Basic ActiveX.dll.
Вот выдержка из документции по Power Basic:
http://basicproduction.nm.ru/
6. Динамическая библиотека.
--------------------------------
Библиотеки, создаваемые PB, являются обычными не ActiveX библиотеками, их не нужно регистрировать в ОС, но функции, которыми вы будете пользоваться, должны быть объявлены в вызывающем модуле.
Пример вызова процедуры из библиотеки, написанной на PB:

'Код для VB:
Private Declare Sub TestSub Lib "testdll.dll" (ByVal StrTest As String)
Private Sub Form_Load()
 Dim Str As String
 Str = "Hello World!"
 TestSub Str
 MsgBox Str, 64
End Sub
'Код для PB:
#Compile Dll "testdll.dll"
Function PBLibMain
 Function = 1
End Function
Sub TestSub Alias "TestSub" (StrTest As Asciiz) Export
    StrTest="Привет Мир!"
End Sub