【问题标题】:TDataset --> Pointer to rows cols matrix?TDataset --> 指向行列矩阵的指针?
【发布时间】:2011-08-20 14:14:32
【问题描述】:

我正在用 Lazarus/FreePascal(如 Delphi)编写一个 Windows 应用程序。我有一个由 5000 行、2 列 数值填充的 TDataset 对象。 我需要将此数据传递给我从 .dll 库静态导入的 C 函数。

这里是库手册的摘录,解释了它的参数应该采用什么格式:

flan_index_t flann_build_index(float* dataset,
    int rows,
    int cols,
    float* speedup,
    struct FLANNParameters* flann_params);

这个函数建立一个索引并返回一个对它的引用。这 此函数预期的参数如下:数据集、行和 cols - 用于指定点的输入数据集: dataset 是指向存储在 row-major 中的 rows cols 矩阵的指针 顺序(每行一个特征)

我可以简单地传递 TDataSet 对象吗?我必须先对它做点什么以使指针的形式正确吗?

【问题讨论】:

  • 这是正确的方法吗?移动(数据集,数据指针[0],SizeOf(数据集));
  • 不,TDataSet 是一个封装与数据文件或 sql 服务器的连接的类。它没有指向函数预期的数据。
  • 没有。 TDataset 具有与函数所需的结构不同的结构。您没有指定矩阵的每个项目的大小,数值有几种类型。抱歉,我无法为使用 Object Pascal 添加 (+1),即使我想这样做 ;-)

标签: c delphi pointers matrix tdataset


【解决方案1】:

显然你不能传递TDataSet 对象。它是一个 FreePascal 对象,该函数似乎需要一个指向 float 的指针(这可能是指向 FreePascal 中的 Single 的指针)。它可能需要float 的二维数组。您必须传递另一个指向 float 的指针和一个指向 FLANNParameters 结构的指针。

Move() 也不起作用。 TDataSet 不是数组。

我猜你必须像 Uwe 所说的那样声明一个数组,使用你的数据集填充它并传递数组:

type
  PMyFloatArray = ^TFloatArray;
  TMyFloatArray = array[0..4999, 0..1] of Single;

var
  MyArray: PMyFloatArray;
  idx: flan_index_t;

begin
  New(MyArray);
  try

    // Fill array using your TDataSet...
    // set up other parameters... 

    idx := flann_build_index(MyArray, 5000, 2, &speedup, etc...);

    // ...

  finally
    Dispose(MyArray);
  end;
end;     

无耻的塞

请阅读我的Pitfalls of Conversion 文章,了解将函数声明从 C 转换为 Delphi(可能还有 Win32 上的 FreePascal)。现在我开始了,您可能也想阅读我的文章Addressing Pointers

【讨论】:

  • 是否有办法通过引用而不是通过在循环中复制值来填充数组?
  • 我可以将其转换为 TMemoryStream,然后将其复制到指针吗?.. 还是浪费时间?
  • 数据在某个地方,您可以使用 DataSet 从那里获取它们。他们不必在一个街区内。
  • 在过去的一两周里,我多次阅读了您的两篇文章的部分内容。它们都是非常有用的文章!非常感谢您创建它们;非常令人印象深刻:)
【解决方案2】:

不,您不能直接传递数据集。命名“数据集”可能暗示这一点,但含义完全不同。您必须将指向浮点矩阵的指针传递给函数。要实现这一点,您应该声明一个浮点数组[0..4999, 0..1](可能是双精度)并从数据集中填充它。

【讨论】:

  • float = Single, double = Double,假设这是 Win32 并且 FreePascal 没有与 Delphi 不同的定义。
  • 谢谢,我对 C 类型不是很熟悉。
  • 在我的回答中看到无耻的插件。 ;-)
  • 如果这个数组包含 100 万个项目,这会是一个显着的速度延迟吗?
  • @Mike,延迟与什么相比?由于无法传递数据集,因此您没有机会采用数组方式。所以它需要它需要的时间。
【解决方案3】:

以 Rudy 的解决方案为基础(顺便谢谢!)我想出了这个:

 with Datasource1.DataSet do
  begin
    Open;
    First;
    field_count := FieldCount;
    record_count := RecordCount;

    row := 0;
    while not EOF do
    begin
      for col := 0 to field_count - 1 do
        MyArray[row, col] := Fields.Fields[col].AsFloat;
      row := row + 1; //Shift to next row in array
      Next; //Shift to next row in dataset
    end;
  end; 

似乎工作得很好;而且比我预期的要快很多。

【讨论】:

    猜你喜欢
    • 2013-01-05
    • 2013-05-27
    • 1970-01-01
    • 2017-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多