【问题标题】:Return double* from c++ dll to delphi program从 c++ dll 返回 double* 到 delphi 程序
【发布时间】:2013-10-23 01:22:06
【问题描述】:

我试图将double 的数组(声明为double*)返回到delphi 程序。在 c++ dll 项目中我有

#define DllExport   __declspec( dllexport )
extern double* array;
extern "C"
{
    DllExport double* SomeMethod(double);
}

在卸载 Dll 时,array 被删除

BOOL APIENTRY DllMain( HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
    )
{

switch( ul_reason_for_call ) 
{ 
...

    case DLL_PROCESS_DETACH:
        delete [] array;
        break;
}
    return TRUE;  // Successful DLL_PROCESS_ATTACH.
}

当我在 c++ 控制台应用程序中测试我的 dll 时,我在使用来自 dll 的 SomeMethod 后得到了正确的结果。接下来我尝试在 Delphi 中测试我的 dll,但方法返回的数组内容是错误的。我使用了以下代码。

TSomeMethod = function(level : Double): PDouble; cdecl;
...
var
    SomeMethod: TSomeMethod;
    arr: PDouble;
...
    if Assigned(SomeMethod) then
        begin
          arr:= SomeMethod(15);
          writeln(arr^:2:0);
          inc(arr);
          writeln(arr^:2:0);
        end
...

从 c++ dll 返回 double* 以在 delphi 中使用的正确方法是什么?

附:其他方法以正确的方式工作。例如 dll 返回char* 而在delphi中我使用PAnsiChar得到它

更新

这是来自写入 SomeMethod 的文件中的一些 C++ 代码。

double* array; // yea it's an array that declared as external in other file;
...
double* SomeMethod(double level)
{
    ...
    deque<double> arrayToReturn;
    ... // some actions with deque
    array= new double[arrayToReturn.size()];
    for (unsigned int i = 0; i<arrayToReturn.size(); i++)
        array[i] = arrayToReturn[i];
    return array;
 }

【问题讨论】:

  • 你有 SomeMethod() 的代码吗?当 SomeMethod() 返回方法中的所有局部变量时消失,因此如果您将值存储在 SomeMethod() 中的局部变量中,它将在返回时消失。这或许可以解释为什么该方法返回垃圾。
  • 要检查的另一件事是,您对 SomeMethod() 使用什么调用约定,是 cdecl 吗?应该是因为您的 Delphi 调用是这样声明的。
  • 为什么是数组extern?定义声明在哪里?显示完整代码。
  • @DavidHeffernan 我使用了 extern 数组,因为我需要在另一个文件中的 SomeMethod 中使用它。我需要我的数组在内存中,直到 Dll 被卸载。在SomeMethod 中,我使用new 运算符为我的数组分配内存。再次在 C++ 控制台应用程序中,我的 Dll 返回正确的数组,但在 Delphi 中却没有。
  • @Arioch'尝试从函数返回宽字符串。将其与在 c++ 端返回 BSTR 的函数匹配。请参阅我的问题清单。或返回一个大型结构。这是一个真正的问题,虽然并不广为人知。

标签: c++ delphi pointers dll dllexport


【解决方案1】:

您问题中的代码运行良好。这意味着问题出在其他地方。证据如下:

C++

#include <Windows.h>

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
    )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

extern "C" {

__declspec(dllexport) double* SomeMethod(double)
{
    double* array = new double[2];
    array[0] = 42;
    array[1] = 666;
    return array;
}

}

德尔福

{$APPTYPE CONSOLE}

uses
  Windows, SysUtils;

type
  TSomeMethod = function(level : Double): PDouble; cdecl;

var
  SomeMethod: TSomeMethod;
  arr: PDouble;
  lib: HMODULE;

begin
  lib := LoadLibrary('MyDll.dll');
  Win32Check(lib<>0);
  SomeMethod := GetProcAddress(lib, 'SomeMethod');
  Win32Check(Assigned(SomeMethod));
  arr:= SomeMethod(15);
  Writeln(arr^:3:0);
  inc(arr);
  Writeln(arr^:3:0);
  Readln;
end.

输出

42 666

【讨论】:

  • 感谢您的帮助和耐心等待。事实上,问题出在 DLL 的另一部分。我在一些例程中使用 c++ 代码中的floor 函数来比较两个double 值。由于某种原因,在 c++ 和 delphi 中它给出了不同的结果。没有floor,一切都按我的意愿进行。
猜你喜欢
  • 1970-01-01
  • 2021-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多