【问题标题】:Help building a Dll for C in Delphi帮助在 Delphi 中为 C 构建一个 Dll
【发布时间】:2010-10-04 14:41:36
【问题描述】:

我之前曾向 another questions 询问过关于构建我的 dll 的问题,但它看起来像是朝着错误的方向 :) 所以我重新制定并解释了更多她。

所以我试图构建的是一个 dll,它将作为我的 delphi 程序和其他人的 C 程序之间的接口。

这个 dll 必须做的是从 C 程序接收一个字符串,然后将它发送到 delphi 程序,在那里它将与一些数据组合并存储在我程序的当前用户下。

如何在我的 Delphi 程序(运行程序)中调用方法来存储来自 dll 的消息?

我正在使用 Delphi 5。 这是我到目前为止得到的:

DLL:

//Parent application: MyDelphiApp   
library MyDllLink; 

uses
  ShareMem,
  SysUtils,
  Classes,
  Dialogs,
  Main;// Main is a form from my delphi app. This is not allowed/recomended ?

{$R *.RES}


procedure Transfer(sMessage: PChar); stdcall;
begin
    try
        //If including Main in the uses clause, then this will also be wrong:
        MainForm.StoreDllMessage(sMessage);
    except
        showmessage('Error');
    end;    
end;

exports
Transfer;

end.

德尔福应用:

procedure TMainForm.StoreDllMessage(sMessage: String);
begin
    //StoreMessage just stores it in a DB
    StoreMessage(sMessage +' '+sCurrentUserName);
end;

【问题讨论】:

    标签: c delphi dll


    【解决方案1】:

    我可能理解错了,但您似乎希望 C 程序和 Delphi 程序同时加载相同的 DLL 副本。你不能做到这一点,只能通过涉及进程间通信的大量工作来真正实现它。应用程序将具有单独的进程空间和内存。

    我会建议一种稍微不同的方法。在 DLL 中有一个名为 SendStringFromCApp 的函数和一个名为 GetStringIntoDelphiApp 的函数(或其他合适的)。

    C 程序将正常加载 DLL 的副本并调用 SendStringFromCApp 函数。该函数会将传入的数据以一些常见的中间格式(例如简单的数据库)进行存储。它将存储视为一种队列,并简单地将数据添加到该队列中。数据库是最明显的选择,但它可以像普通目录一样简单,并且数据存储为小文本文件,文件名是递增的整数。

    Delphi 程序将加载它自己的 DLL 副本并调用 GetStringIntoDelphiApp,它将从队列/内部存储中读取第一项并根据需要对其进行处理,然后将其从存储中删除。然后它将读取下一个等。

    这样做的好处是 C 和 Delphi 应用程序都可以独立运行。只有 DLL 需要一个通用配置,即使 Delphi 应用程序没有运行,C 程序也可以继续工作,反之亦然。

    它基本上是一个用于不同进程的生产者-消费者排队系统。

    就像我说的,我可能误解了要求!

    【讨论】:

    • 它需要“立即”发生,所以这种方法对我根本不起作用。 C 应用程序发送的信息需要存储在数据库中的哪个位置,经常变化,因此这种延迟会导致数据存储在错误的位置。
    • 很公平。在这种情况下,我会考虑使用来自 C 应用程序(或通过 DLL)的 Windows WM_COPYDATA 消息发布到您的 Delphi 应用程序。在这种情况下,只有 C 应用程序需要访问 DLL。尝试在进程之间共享 DLL 是行不通的。
    【解决方案2】:

    【讨论】:

    • 我正在尝试使用 WM_Copydata,但在我的 delphi 应用程序中注册消息时遇到问题,所以今天晚些时候可能会弹出另一个问题 :)
    • 好吧,你不需要注册消息,只需要找到目标HWND并发送它。 WM_COPYDATA 消息将到达目标消息队列。
    【解决方案3】:

    尝试实现 IPC(进程间通信)。您将有 3 个独立的进程。

    1. Delphi exe
    2. C 程序
    3. 非窗口进程(com 服务、exe、...)

    使用非窗口作为服务器,其他2个是客户端。 Delphi 中的 IPC 参见this,C 中的 IPC 参见this。有很多方法可以实现 IPC。如果你在你最喜欢的搜索引擎中寻找 IPC,我很确定你会找到一种为 C 和 Delphi 进行 IPC 的常用方法,因为它只是一些 win32 api 芭蕾。

    【讨论】:

    • 由于我不打算对 C 部分进行编程,因此使用这种方法很复杂。
    • 还有一个由 C 程序调用的 dll 接收字符串的情况。而那个 dll 单独通过 IPC 与 Delphi 程序进行通信。在两个 delphi 进程之间,使用这些组件 'home.roadrunner.com/~rllibby/source.html' 进行 IPC 非常容易,去那里寻找 'pipes.zip'。您将拥有一个 TPipeServer 和一个 TPipeClient
    【解决方案4】:

    正如 loursonwinny 所说,IPC 是必经之路。
    您应该了解每个 DLL 都是在单个应用程序的地址空间中加载的。因此,Delphi 和 C 应用程序使用的 DLL 将在内存中存在两次。 (嗯,不完全,代码部分是共享的,DLL 中的所有数据都存在两次。)所以基本上你的 DLL 不能简单地在两个进程之间共享数据。
    当然,也有例外。例如,可以在加载到 Delphi 应用程序中的单个 DLL 中创建键盘挂钩,然后将其注入到 C 进程的地址空间中。然后,DLL 可以“窥视”C 应用程序的内存空间并捕获一些信息。 (带有 KeyHooks 的键盘事件。)但是 KeyHooks 和类似的可注入 DLL 会被一般的防病毒产品视为“坏”。并且有充分的理由,因为这是计算机病毒所期望的行为。
    替代 IPC 的另一种解决方案是使用memory mapped file。有几个组件可作为开源或商业使用,但您也可以使用 Windows API 来创建这些组件。
    Windows API 还提供了命名管道和邮件槽等技术,它们也可用于进程间通信。它不需要是 TCP/IP,但您需要某种方式让两个进程相互通信。而且这个逻辑确实可以构建在单个 DLL 中,您只需在其中定义两个方法。一个用于服务器,一个用于客户端。不过,这是一项复杂的技术。而且 Delphi 5 有点老了,所以我不知道哪种解决方案最适合您。

    【讨论】:

      【解决方案5】:

      DLL 必须回调到 Delphi 程序。当 Delphi 程序启动时,它会注册一个回调函数。这样 DLL 就知道当它被 C 程序调用时要调用什么。

      示例: http://delphi.about.com/od/windowsshellapi/a/callback_delphi.htm 此示例使用回调来允许 Windows API 回调到您的 delphi 应用程序。这里的想法相同,但您将由您自己的 DLL 调用,而不是 Windows API。

      【讨论】:

      • 以前从未使用过回调,将研究它。如果您有任何教程,请随时链接到一些教程:)
      • @Shunty 是对的——内存模型不起作用。即 C 程序将调用 DLL 的另一个实例,而不是附加到您的应用程序的实例。最好让 DLL 向您发送 WM 消息,写入简单的数据库,使用邮槽等。
      • 对,每个程序都会为dll分配不同的内存空间,c程序推送数据时不会触发从Delphi注册的回调...
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-06
      • 1970-01-01
      • 2011-08-02
      • 1970-01-01
      • 2016-09-25
      相关资源
      最近更新 更多