float* 从 C 到 C#

发布于 2024-10-21 07:06:48 字数 840 浏览 3 评论 0原文

我不是一个真正的 CS 人,所以如果这里的任何一位天才能够为我指明正确的方向,我将永远感激不已。

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

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

这非常有效。我现在需要将其放入 C# 程序中,而这就是事情变得混乱的地方。

为了避免 char ** ,我做的第一件事就是使参数成为一系列布尔值。如果我允许它仍然转储到文件,效果很好。

问题是在 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 释放它(也许这是错误的?)

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

I'm not truly a CS guy, so if any of you geniuses on here can point me in the right direction I'll be eternally grateful.

I have a c-code command line function that used to write its results to file. I converted it to return it's data via a float* array to a C++ program like such (to avoid constant file I/O):

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

This worked perfectly. I now need to get this into a C# program, and here's where things go haywire.

The first thing I did to avoid the char ** was to make the arguments a series of bool. That worked fine if I allow it to still dump to file.

The problem is juggling the c-style float array in C#. Within the c-code it was allocated with malloc.

So here's everything I've tried with no success(I know the size of the array):

  1. Make a "free" function to export to call from C# to release the memory when I'm done with it. After a few loops the C# crashes with no warning.

  2. Release the malloc from C# with Marshal.FreeCoTaskMem. Same result.

  3. Move the float* to an argument and remove the c-code malloc. (void mgrib(..., float* data,...)

__a)Allocate it with Marshal.AllocCoTaskMem. Free it with Marshal.FreeCoTaskMem.

__b)Use Marshal.Copy to allocate. Free it with Marshal.FreeCoTaskMem (Maybe this is wrong?)

I've dabbled in just about everything I could find in the internet. Please let me know if more info is necessary. I'm hoping this just a simple concept that I'm missing.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

汹涌人海 2024-10-28 07:06:48

将此签名用于您的 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 );

Use this signature for your C function (replace the mgrib.dll with real library name).

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

Call the mgrib function as follows:

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

When the call is done, you can get the result like this:

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

EDIT:

Since the mgrib is allocating the memory using malloc, we need to free the memory using free function. However, you will have to wrap the call to free function in another function that will be exported from native library.

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

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

And then import it into like this:

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

And invoke it as follows:

mgrib_free( pointer );
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文