Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将数据从Delphi DLL传递到C++;应用 我在Delphi中编写了一个DLL,它应该确定一些值,然后将结果传递给C++应用程序,称为DLL。 将传递回C++应用程序的数据是一组四个整数值(但将来也可能有字符串值)。_C++_Delphi_Dll_Delphi 2009 - Fatal编程技术网

将数据从Delphi DLL传递到C++;应用 我在Delphi中编写了一个DLL,它应该确定一些值,然后将结果传递给C++应用程序,称为DLL。 将传递回C++应用程序的数据是一组四个整数值(但将来也可能有字符串值)。

将数据从Delphi DLL传递到C++;应用 我在Delphi中编写了一个DLL,它应该确定一些值,然后将结果传递给C++应用程序,称为DLL。 将传递回C++应用程序的数据是一组四个整数值(但将来也可能有字符串值)。,c++,delphi,dll,delphi-2009,C++,Delphi,Dll,Delphi 2009,为了做到这一点,我需要声明这些整数值在调用应用程序和DLL之间共享 在C++应用程序侧,我可以这样做(根据): 如何在Delphi 2009中执行相同的操作(声明value1-N将存储在共享内存中) 更新,18.09.2012:我决定使用命名管道来实现注入DLL与外部世界的通信 但在使用命名管道之前,我需要解决以下问题 目前,流程如下所示: 1) DLL被注入到遗留应用程序中 2) DLL从遗留应用程序中提取一些数据 3) DLL已卸载 我需要对其进行修改,使其工作方式如下: 1) DLL被注入

为了做到这一点,我需要声明这些整数值在调用应用程序和DLL之间共享

在C++应用程序侧,我可以这样做(根据):

如何在Delphi 2009中执行相同的操作(声明value1-N将存储在共享内存中)

更新,18.09.2012:我决定使用命名管道来实现注入DLL与外部世界的通信

但在使用命名管道之前,我需要解决以下问题

目前,流程如下所示:

1) DLL被注入到遗留应用程序中

2) DLL从遗留应用程序中提取一些数据

3) DLL已卸载

我需要对其进行修改,使其工作方式如下:

1) DLL被注入到遗留应用程序中。 2) DLL启动一个循环,就像

bool running = true;
while (running)
{
    command = receiveCommandFromInvokingApp();
    if ("GET_COORDINATES".equals(command))
    {
        // Read coordinates of some cell in the grid
        // Then communicate it via some channel to the outside world
    }
    else if ("READ_CELL_VALUE")
    {
        // Read value of some cell in the grid
        // Then communicate it via some channel to the outside world
    }
    else if ("EXIT")
    {
        // Close the communication channel
        // Perform cleanup work
        running = false;
    }

    // Sleep for, say, 500 milliseconds in order to avoid 100 % CPU usage
}
receiveCommandFromInvokingApp读取从调用应用程序(从命名管道或任何其他合适的通道)发送的下一个命令

3) 当调用应用程序发送EXIT命令时,DLL停止循环

假设我有以下DLL代码:

procedure DllMain(reason: integer) ;
begin
  if reason = DLL_PROCESS_DETACH then
    OutputDebugString('DLL PROCESS DETACH')
  else if reason = DLL_THREAD_ATTACH then
    OutputDebugString('DLL THREAD ATTACH')
  else if reason = DLL_THREAD_DETACH then
    OutputDebugString('DLL THREAD DETACH')
  else if reason = DLL_PROCESS_ATTACH then
    OutputDebugString('DLL_PROCESS_ATTACH')
  end;
end; (*DllMain*)
循环应该放在哪里(在哪个分支中)

将其替换为
OutputDebugString('DLL线程连接')
是否明智

2012年9月19日更新:

我的系统的设计改变了,现在我通过命名管道将数据从Delphi DLL发送到C#应用程序

Delphi代码:

打开命名管道:

function OpenNamedPipe() : THandle;
var
  hPipe : THandle;
  name : string;
  connectResult : LongBool;
begin
  name := '\\.\pipe\delphi-to-cpp';
  hPipe := CreateNamedPipe(PChar(name),
    PIPE_ACCESS_DUPLEX,
    PIPE_TYPE_MESSAGE or PIPE_READMODE_MESSAGE  or PIPE_NOWAIT,
    PIPE_UNLIMITED_INSTANCES,
    4096 ,
    4096 ,
    4096 ,
    NIL);
  if (hPipe = INVALID_HANDLE_VALUE) then
  begin
    OutputDebugString(PChar('Invalid pipe handle: ' + IntToStr(GetLastError)));
    OutputDebugString(PChar(SysErrorMessage(GetLastError)));
  end;


  OutputDebugString(PChar('OpenNamedPipe, 1'));
  connectResult := ConnectNamedPipe(hPipe, NIL);
  OutputDebugString(PChar('connectResult: ' + BoolToStr(connectResult)));
  OutputDebugString(PChar(SysErrorMessage(GetLastError)));

  OpenNamedPipe := hPipe;
end;
发送消息:

procedure SendMessageToNamedPipe(hPipe:THandle; msg:string);
var
  dwWrite : DWORD;
  lpNumberOfBytesWritten : LongBool;
  MsgLength: DWORD;
  MsgW : PWideChar;
begin
  MsgW := PWideChar(msg);
  MsgLength := lstrlenW(MsgW) * SizeOf(WideChar);
  lpNumberOfBytesWritten := WriteFile(hPipe, MsgW, MsgLength, dwWrite, NIL);

  if not lpNumberOfBytesWritten then
  begin
    OutputDebugString(PChar('Sending error: ' + SysErrorMessage(GetLastError)));
  end
  else
  begin
    OutputDebugString(PChar('Message sent, dwWrite: ' + IntToStr(dwWrite)));
  end;
end;
C#代码,应读取Delphi应用程序发送的数据:

  NamedPipeClientStream pipeClient = new NamedPipeClientStream(".", "delphi-to-cpp",
      PipeDirection.InOut);

  new NamedPipeClientStream(".", "delphi-to-cpp",
      PipeDirection.InOut);

  Debug.WriteLine("Before pipeClient.Connect");

  this.IsRunning = true;


  pipeClient.Connect(5000);
  StreamReader reader = new StreamReader(pipeClient, Encoding.Unicode);

  while (this.IsRunning && pipeClient.IsConnected)
  {
      string message = reader.ReadLine();

      Thread.Sleep(250);
  }
  reader.Close();
此代码无效-
reader.ReadLine()不返回任何内容

如果我试图将数据按字节读入
char[]
缓冲区,则该缓冲区在读取结束时包含垃圾

请注意,C#应用程序实际上正在接收某些内容,我只是不知道如何从流中提取文本


我应该如何修改我的代码(Delphi、C#或两者),以便Delphi应用程序发送的文本正确到达C#端?

Delphi工具链没有内置的功能

为了在Delphi中执行类似的操作,您需要使用内存映射文件API或一些其他进程间通信(IPC)机制,例如管道、套接字、Windows消息等

或者,您可以从Delphi DLL中简单加载C++ DLL。C++ DLL可以访问共享数据,而Delphi DLL可以调用C++ DLL中的函数来读取和写入共享数据。然而,共享数据确实非常不适合这项任务。使用IPC更合适


你在问题中没有说清楚的是,这里有两个过程。因此需要IPC。

在我看来,这个解决方案有很多错误。将全局变量用作返回机制的想法已经是一个非常糟糕的想法——如果多个进程正在运行,则不是线程安全/复杂的。还值得注意的是,DLL的所有实例都将共享此空间

我肯定会:

> P>将一个空结构从C++传递到Delphi,Delphi侧填充(或者您需要使用缓冲区而不是指针),或者

  • 将指向字段的指针传递给delphi进程,并允许DLL更新这些指针处的值或

  • < P>将这些结果存储在DLL中的全局变量中,并创建单独的函数调用,以从C++中检索值。即int getValueA()


    另一方面,正如David所建议的,可以使用更重的进程间通信机制,但在这种情况下,这似乎是一种过激行为。当我阅读问题时,根据海报上最近的一系列问题,这里实际上有两个进程。因此,需要IPC.是-不清楚:他说:“把结果传递给C++应用程序,称为DLL”。已要求澄清。您能否澄清您的问题是否涉及同一进程(即此exe启动DLL)的exe和DLL之间的通信或作为单独进程运行?值得一提的是,我认为您没有充分利用堆栈溢出。您已经为您的问题提出了4或5个建议的解决方案,然后将每个解决方案都分解。如果你回到一开始就提出你的问题会更好。问题是,“你能为这个问题推荐一个解决方案吗?”?我的建议是自动热键,但你可能会得到其他更好的建议。实际上,我打算使用类似于自动热键的东西。我想做的是将文本写入网格单元(x,y)是一个获取单元的坐标(这已经工作了,我尝试过了),然后b)将这些坐标从Delphi DLL传递到C++应用程序(使用命名管道),C)双击该位置并键入文本。第a部分)已实施。第三部分)很简单(我以前做过)。因此,目前最困难的部分是B)-将Delphi DLL的值传递回C++。窗口消息比命名管道更容易。不过,您需要运行消息泵。这在另一个线程中可能更容易。我在上找到了一个用于在Delphi中使用命名管道的库。但是没有说明如何使用它(源代码作者的页面没有)。有没有关于如何在Delphi中打开命名管道并将数据写入命名管道的教程?在Delphi中使用命名管道与使用任何其他语言完全相同。在C++中找到一个使用原始Win32 API的教程,然后从那里开始。
      NamedPipeClientStream pipeClient = new NamedPipeClientStream(".", "delphi-to-cpp",
          PipeDirection.InOut);
    
      new NamedPipeClientStream(".", "delphi-to-cpp",
          PipeDirection.InOut);
    
      Debug.WriteLine("Before pipeClient.Connect");
    
      this.IsRunning = true;
    
    
      pipeClient.Connect(5000);
      StreamReader reader = new StreamReader(pipeClient, Encoding.Unicode);
    
      while (this.IsRunning && pipeClient.IsConnected)
      {
          string message = reader.ReadLine();
    
          Thread.Sleep(250);
      }
      reader.Close();