【问题标题】:C++ to C# wrapping - how to handle array of double pointers from C#C++ 到 C# 包装 - 如何处理来自 C# 的双指针数组
【发布时间】:2015-01-03 09:32:37
【问题描述】:

我已经浏览这个网站很长时间了,并感谢您对其他人问题的回答 - 现在,唉,我不得不通过问自己的问题来表明我的无知。我搜索了现有的等价物,但找不到;如果这是重复的,我深表歉意。

我正在尝试使用 .Net 4.0 框架下的 Visual C# Winforms 应用程序中的非托管 Windows DLL(Intel Power Gadget 3.0 API,FWIW)。该 API 是在考虑 C++ 实现的情况下编写的,所以我必须随时翻译。我已经能够包装和实现该库的大部分功能,但我对此感到困惑:

bool GetPowerData(int iNode, int iMSR, double *pResult, int *nResult);

...作者是这样描述的(我的重点):

返回最近一次调用 ReadSample() 收集的数据。 返回的数据是针对iNode指定的包上的数据, 来自 iMSR 指定的 MSR。 数据在pResult中返回,并且 pResult 中返回的双精度结果数 nResult。参考表1:MSR函数。

(https://software.intel.com/en-us/blogs/2014/01/07/using-the-intel-power-gadget-30-api-on-windows)

关键点:该函数以指向双精度数组的指针的形式返回其主要数据 - 还是指向双精度数组的指针? ...什么级别的间接?这就是我开始变得不确定的地方! :)

至少一些的输入参数是简单的; iNodeiMSRints,我知道并且已经可以获得的值。

我已经用这个签名在我的 C# 代码中声明了这个函数:

[DllImport("EnergyLib32.dll", CallingConvention = CallingConvention.Cdecl)]
    static extern bool GetPowerData(int iNode, int iMSR, out IntPtr pResult, ref int nResult);

(我确定这是我的第一个错误,就在那里。)

至于实际调用该函数,我尝试了各种可能性,都太丑了,甚至无法在这里展示。

能否请比我知识渊博的人提出处理此函数及其返回值的最佳方法?

提前谢谢你。

【问题讨论】:

  • 指针和数组在 C++ 中(几乎)是相同的。这就是为什么一个双精度数组作为double * 返回的原因。看看cplusplus.com/doc/tutorial/pointers/#arrays
  • 感谢 rsenna 的快速而有帮助的回复。您链接到的文章是我见过的对 C++ 中数组的更好解释之一。不幸的是,您认为我对此比实际情况更了解 - 我将继续研究:)
  • 不客气! :) 那是我当时能提供的最好的,希望它有所帮助。
  • rsenna> 是的,它帮助我理解了更多。再次感谢。
  • 尊敬的未来访客 - 正确答案由下面的“DBC”给出;我已经确认它有效。我希望这对您有所帮助。

标签: c# arrays pointers dllimport unmanaged


【解决方案1】:

该文档不清楚。因为它是一个double * 来填充多个结果,所以您需要传入一个 preallocated 数组——但是该数组应该有多大? doc 表示以下内容:

API 从 GetMsrFunc() 获得的 MSR 函数确定从 GetPowerData() 返回的数据的数量和含义,如表 1 所述。

表1中我们看到:

  • MSR 0:1 双。
  • MSR 1:3 双打。
  • MSR 2:2 双打。
  • MSR 3:1 双。

因此,一个包含 3 个双精度数的数组应该足以容纳所有可能的返回数据。 sample c++ source 证实了这一点

        for (int j = 0; j < numMsrs; j++)
        {
            int funcID;
            energyLib.GetMsrFunc(j, &funcID);
            double data[3];
            int nData;
            wchar_t szName[MAX_PATH];

            energyLib.GetPowerData(currentNode, j, data, &nData);
            energyLib.GetMsrName(j, szName);

所以你可以这样声明:

    [DllImport("EnergyLib32.dll", CallingConvention = CallingConvention.Cdecl)]
    static extern bool GetPowerData(int iNode, int iMSR, [In, Out] double [] pResult, out int nResult);

要调用它,请使用

    double [] result = new double[3];

有关将数组传递给非托管代码的讨论,请参阅here

(注意 - 答案未经测试。)

【讨论】:

  • 谢谢。这非常有效,我现在可以通过 GetPowerData() 调用获取值。非常感谢您清晰明了的解释!
【解决方案2】:

正确答案(从某种意义上说,它对我有用 - YMMV! - 由 DBC 及时且清晰地发布。 这是我使用的,基于 DBC 的 cmets:

声明:

[DllImport("EnergyLib64.dll", CallingConvention = CallingConvention.Cdecl)]
    static extern bool GetPowerData(int iNode, int iMSR, [In, Out] double[] pResult, out int nResult);

及用法:

double[] result = new double[4];
....
bResult = GetPowerData(0, iModeLocal, result, out nResult); // where iModeLocal is an integer that determines the type of data (MSR) I'm interested in

很久以前我没有将其标记为“已回答”的唯一原因是我没有意识到我没有。哎呀。对不起。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    • 2021-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多