TBitmap32 как аргумент функции в DLL - PullRequest
1 голос
/ 16 апреля 2020

Я хочу создать DLL с некоторыми функциями, чтобы упростить управление кодом, обновить программу и т.д. c. Я не хочу, чтобы другие языки программирования использовали мою DLL, просто Delphi.

Так что в этом случае безопасно передавать строки и объекты в качестве аргументов? Вот так:

function LoadImage(Filename: AnsiString; Bmp32: TBitmap32): Integer;
begin
//
end;

Будет ли такая DLL нормально работать с разными версиями Delphi?

Ответы [ 3 ]

5 голосов
/ 16 апреля 2020

Будет ли такая DLL нормально работать с различными версиями Delphi?

Нет, как для строк, так и для классов.

Для строк это может работать, если вы используйте диспетчер разделяемой памяти, и версии Delphi имеют одинаковую реализацию для строк. Это не то, что часто меняется, так что вы часто можете сойти с рук. И вы часто можете обойтись без него в зависимости от того, как передан параметр (const, по значению, var, et c.) И что делает с ним вызываемый.

Давайте теперь посмотрим на классы. Расположение класса может варьироваться в зависимости от версии Delphi и, более вероятно, от разных версий graphics32.

Даже если бы это было не так, это было бы небезопасно. Причина в том, что у вас есть два экземпляра RTL / VCL. Один в исполняемом файле хоста, один в DLL. Когда исполняемый файл хоста создает экземпляр, он ожидает работы с экземпляром RTL / VCL в исполняемом файле хоста. Но когда вы передаете его в DLL и вызываете не виртуальный метод, выполняемый код является кодом в DLL, который ожидает RTL / VCL-экземпляр DLL.

Пакеты предназначены для решения этой проблемы. проблема. Используйте пакеты времени выполнения, и вы разрешите всем модулям использовать один и тот же экземпляр RTL / VCL.

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

1 голос
/ 16 апреля 2020

AnsiStrings должно работать нормально, если вы включите ShareMem в раздел пользователей в качестве первой записи (в начале каждого нового проекта DLL есть большой комментарий по поводу этой топики c! Пожалуйста, прочтите его внимательно.)

На ваш вопрос об использовании объектов в качестве аргументов функций / процедур DLL:
Этот подход небезопасен, поскольку вы не можете быть уверены, что версия используемого класса одинакова как в приложении хоста, так и в библиотеке DLL. !

Существует очень хорошая статья о DLL от Rudy Velthius для более подробной информации здесь .

1 голос
/ 16 апреля 2020

Передача объекта в DLL является грязной (fr agile, не рекомендуется). Настолько, что я отказался от этого какое-то время go. Теперь, если я хочу передать объект в DLL, я делаю это через интерфейс.

Если вы намерены придерживаться этого пути, есть несколько вещей, которые вам нужно знать.

Во-первых, скорее всего (определенно?) Не будет работать для другой версии Delphi.

Может не работать, если вы не собрали EXE и DLL с точной те же параметры компиляции.

Это может все еще не работать, если вы скомпилировали с точно такими же параметрами компиляции.

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

function Sample(AStrings : TStringList) : Boolean;
var vStrings : TStringList;
begin
  vStrings := TStringList.Create;
  try
    AStrings.Assign(vStrings); //ERROR : Cannot assign a TStringList to a TStringList
  finally
    vStrings.Free;
  end;
end;

Это происходит потому, что DLL и EXE не имеют одинаковые ссылки на класс. У них обоих есть собственное определение TStringList, и они несовместимы.

Так что, в зависимости от того, что делает ваша функция, вам, вероятно, понадобится TBitmap32 в пакете времени выполнения. И в зависимости от того, что делает TBitmap32, вам также понадобится пакет времени исполнения с каждым классом, который он использует, прямо или косвенно.

Возможно, есть еще кое-что ... Я перестал исследовать это минное поле длиной go.

...