【问题标题】:float* from C to C#float* 从 C 到 C#
【发布时间】:2011-07-11 08:05:27
【问题描述】:

我不是真正的 CS 人,所以如果你们这里的任何天才能指出我正确的方向,我将永远感激不尽。

我有一个用于将其结果写入文件的 c 代码命令行函数。我将其转换为通过 float* 数组将其数据返回到这样的 C++ 程序(以避免常量文件 I/O):

float * mgrib(int argc, char **argv)

这非常有效。我现在需要把它放到一个 C# 程序中,这就是事情变得混乱的地方。

为了避免 char **,我做的第一件事就是将参数设为一系列 bool。如果我允许它仍然转储到文件,那效果很好。

问题是在 C# 中处理 c 样式的浮点数组。在 c 代码中,它是用 malloc 分配的。

所以这是我尝试过但没有成功的所有内容(我知道数组的大小):

  1. 创建一个“免费”函数以导出以从 C# 调用,以便在我完成后释放内存。几个循环后,C# 崩溃,没有任何警告。

  2. 使用 Marshal.FreeCoTaskMem 从 C# 中释放 malloc。结果一样。

  3. 将 float* 移至参数并删除 c 代码 malloc。 (void mgrib(..., float* data,...)

__a) 使用 Marshal.AllocCoTaskMem 分配它。使用 Marshal.FreeCoTaskMem 释放它。

__b) 使用 Marshal.Copy 进行分配。使用 Marshal.FreeCoTaskMem 释放它(也许这是错误的?)

我几乎涉足了我在互联网上能找到的所有内容。如果需要更多信息,请告诉我。我希望这只是我缺少的一个简单概念。

【问题讨论】:

  • 忘记 C 原型,用 C# 编写一个干净的原型。而是返回一个浮点数组 (float[])。
  • 请贴出你的c#代码
  • 你是想把这件事做好,还是很容易做到?简单的方法是让两个程序几乎完好无损,但通过管道而不是文件进行通信。要想做得好,最好用一种语言编写整个程序。
  • 我现在很擅长 c#,但是 c 代码太弱了,无法将完整的(非常大的)程序从 c 转换为 c#。我真希望这是一个选择。我会尝试下面的建议,如果不成功发布一些 c# (这很痛苦,因为机器没有连接,所以我需要将它运动起来),虽然它主要是循环中的 Dllimport 调用。跨度>

标签: c# c pointers malloc marshalling


【解决方案1】:

将此签名用于您的 C 函数(将 mgrib.dll 替换为真实库名称)。

[DllImport( "mgrib.dll", EntryPoint = "mgrib" )]
public static extern IntPtr mgrib(
    int argc,
    [MarshalAs( UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPStr )]
    StringBuilder[] argv );

调用mgrib函数如下:

// Prepare arguments in proper manner
int argc = 0;
StringBuilder[] argv = new StringBuilder[ argc ];
IntPtr pointer = mgrib( argc, argv );

调用完成后,可以得到如下结果:

float[] result = new float[ size ];
Marshal.Copy( pointer, result, 0, size );

编辑

由于mgrib 使用malloc 分配内存,我们需要使用free 函数释放内存。但是,您必须将对 free 函数的调用包装在另一个将从本机库导出的函数中。

extern "C" __declspec(dllexport) void mgrib_free( float* pointer );

void mgrib_free( float* pointer )
{
    free( result );
}

然后像这样导入:

[DllImport( "mgrib.dll", EntryPoint = "mgrib_free",
            CallingConvention = CallingConvention.Cdecl )]
public static extern void mgrib_free( IntPtr pointer );

并按如下方式调用它:

mgrib_free( pointer );

【讨论】:

  • 休息,非常感谢您的详细回复。这实际上正是我为我的许多尝试之一所做的。您的回答让我有信心深入研究并逐步完成每次迭代(呃)。我发现,在访问“mgrib”256 次后,无论程序如何崩溃而没有任何警告。这有点太巧合了。我正在使用 Marshal.FreeCoTaskMem。 Marshal.FreeHGlobal 引发句柄错误。所以我认为现在很清楚 FreeCoTaskMem 并没有完全削减它,不知何故内存没有被释放。有什么想法吗?
  • 这是我尝试的第一件事,但在我学会如何使用 IntPtr 之前。我会试一试。感谢您回到这里。
  • 事实证明,当我返回我感兴趣的数据时,我正在切断 c 代码中另一个指针的破坏。非常感谢试图帮助我解决自己的愚蠢问题;) !
猜你喜欢
  • 2018-11-29
  • 2018-05-23
  • 1970-01-01
  • 1970-01-01
  • 2021-01-13
  • 2012-01-04
  • 1970-01-01
  • 2017-07-20
  • 1970-01-01
相关资源
最近更新 更多