简体   繁体   English

TBitmap32 作为 DLL 中的 function 参数

[英]TBitmap32 as a function argument in a DLL

I want to create a DLL with some of the functions in order to make it easier to manager code, update the program etc. I don't want any other programming languages to use my DLL, just Delphi.我想创建一个具有一些功能的 DLL,以便更轻松地管理代码、更新程序等。我不希望任何其他编程语言使用我的 DLL,只是 Z4C4A218DB8E569D153ACC8A4533C。

So in this case it it safe to pass Strings and objects as arguments?那么在这种情况下,将字符串和对象作为 arguments 传递是否安全? Like this:像这样:

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

Will such DLL work fine with different versions of Delphi?这样的 DLL 能否与不同版本的 Delphi 一起正常工作?

Will such DLL work fine with different versions of Delphi?这样的 DLL 能否与不同版本的 Delphi 一起正常工作?

No, for both strings and classes.不,对于字符串和类。

For strings, it can work if you use a shared memory manager, and the Delphi versions have the same implementation for strings.对于字符串,如果您使用共享的 memory 管理器,它可以工作,并且 Delphi 版本对字符串具有相同的实现。 That's not something that changes frequently, so you can often get away with it.这不是经常变化的东西,所以你经常可以侥幸逃脱。 And you can often get away with it depending on how the parameter is passed (const, by value, var, etc.) and what the callee does with it.而且您通常可以根据参数的传递方式(const、按值、var 等)以及被调用者对它的处理方式来逃避它。

Let's look at classes now.现在让我们看看课程。 The layout of the class can vary between different versions of Delphi, and more likely different versions of graphics32. class 的布局可能因 Delphi 的不同版本而异,更可能是不同版本的图形 32。

Even if that were not the case it would not be safe.即使不是这样,它也不安全。 The reason being the you have two instances of the RTL/VCL.原因是您有两个 RTL/VCL 实例。 One in the host executable, one in the DLL.一个在主机可执行文件中,一个在 DLL 中。 When the host executable creates an instance, that instance is expecting to work with the RTL/VCL instance in the host executable.当主机可执行文件创建一个实例时,该实例期望与主机可执行文件中的 RTL/VCL 实例一起工作。 But when you pass it to the DLL and call a non-virtual method, the code that executes is the code in the DLL, which expects the RTL/VCL instance of the DLL.但是当你将它传递给 DLL 并调用非虚拟方法时,执行的代码是 DLL 中的代码,它需要 Z5884E40D596AD90E5406F271 的 RTL/VCL 实例。

Packages are designed to solve this problem.软件包旨在解决这个问题。 Use runtime packages, and you allow all modules to share the same RTL/VCL instance.使用运行时包,您允许所有模块共享同一个 RTL/VCL 实例。

Of course packages force all parties to use the same Delphi version.当然包强制各方使用相同的 Delphi 版本。 You might not want that.你可能不想要那个。 In which case the remaining option for you is to expose the functionality using interfaces.在这种情况下,您剩下的选择是使用接口公开功能。

Passing object to DLL is messy (fragile, unadviseable).将 object 传递给 DLL 是混乱的(脆弱,不建议)。 So much so that I gave up on that a while ago.以至于我不久前就放弃了。 Now, if I want to pass an object to a DLL, I do it through an interface.现在,如果我想将 object 传递给 DLL,我可以通过接口进行。

If you intend to keep on this path, there is a few thing you need to know.如果你打算继续走这条路,你需要知道一些事情。

First, it most likely (definitely?) won't work for different version of Delphi.首先,它很可能(肯定?)不适用于不同版本的 Delphi。

It may not work if you didn't build the EXE and DLL with the exact same compile options.如果您没有使用完全相同的编译选项构建 EXE 和 DLL,它可能无法正常工作。

It might still not work if you compiled with exactly the same compile options.如果您使用完全相同的编译选项进行编译,它可能仍然无法工作。

If you don't build both EXE and DLL with runtime package, weird stuff can happen, like如果你不使用运行时 package 构建 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;

This happens because the DLL and the EXE don't have the same class reference.发生这种情况是因为 DLL 和 EXE 没有相同的 class 参考。 They both have their own definition of TStringList and they are incompatible.它们都有自己的 TStringList 定义,并且不兼容。

So, depending on what your function do, you would probably need to have the TBitmap32 in a runtime package.因此,根据您的 function 所做的事情,您可能需要在运行时 package 中使用 TBitmap32。 And depending on what TBitmap32 does, you would also need to have a runtime package with every classes it uses, directly or indirectly.并且根据 TBitmap32 的功能,您还需要直接或间接使用它使用的每个类的运行时 package。

There's probably more... I stopped researching that minefield long ago.可能还有更多……我很久以前就停止研究那个雷区了。

AnsiStrings should work fine if you include ShareMem to the uses section as the first entry (there is a big comment about this topic at the beginning of each new DLL project. Please read it carefully.)如果您将ShareMem作为第一个条目包含在使用部分中,AnsiStrings 应该可以正常工作(每个新的 DLL 项目的开头都有关于此主题的大注释。请仔细阅读。)

For your question about using objects as arguments to DLL functions/procedures:关于将对象用作 arguments 到 DLL 函数/程序的问题:
This approach is not secure because you can't be sure that the version of used class is the same in both the host app and the DLL!这种方法不安全,因为您无法确定使用的 class 的版本在主机应用程序和 DLL 中是否相同!

There is a very nice article about DLLs by Rudy Velthius for more detail information here . Rudy Velthius 有一篇关于 DLL 的非常好的文章,可在此处获取更多详细信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM