【问题标题】:C# call to C and pass parameter as a pointer to an arrayC# 调用 C 并将参数作为指向数组的指针传递
【发布时间】:2021-08-31 02:56:45
【问题描述】:

我有一个带有以下签名的 C 方法:

extern __declspec(dllexport) int my_func
    (const double(*points)[3], double parameters[MAXPARS], int* numberofparameters);

此函数是 .lib 的一部分,我将其包装在用 C++ 编写的 DLL (CLR/CLI) 中,以便我可以从 C# 调用。 C++方法的签名类似:

int MyFunc(const double(*points)[3],
            double parameters[MAXPARS],
            int* numberofparameters)

现在我的困难是如何从 C# 调用这个方法。问题是第一个参数,const double(*points)[3],不知道怎么传。 我在 C# 中的代码如下所示:

double[,] pts = new double[1,3];
pts[0, 0] = 1.5;
pts[0, 1] = 2.5;
pts[0, 2] = 3.5;

double[] parameters = new double[4];
int nrParams;
unsafe {
    fixed (double *points = pts) {
       fixed (double* para = &parameters[0]) {
          wrapper.MyFunc(&points, para, &nrParams);
       }

    }
}

这显示了错误: 参数 1:无法从 double** 转换为 $ArrayType ....

任何帮助将不胜感激。

谢谢,

您好,

Sorin

【问题讨论】:

  • C 还是 C++?你在标题中说 C,你说你“有一个 C 方法”,然后你说 C++,你也标记了 C++。
  • 对,因为我将 C 方法包装到 C++ DLL 中,就像我说的那样; C++ 方法与 C 方法具有相同的签名
  • double parameters[MAXPARS] - 注意给定的长度参数被完全忽略,表达式等价于double parameters[]double* parameters。如果您出于文档目的而意识到这一点,那很好,但是您的进一步期望不会得到满足。还要注意,第一个参数在这方面有所不同(指向大小为 3 的数组的指针)。
  • 在 C 或 C++ 中是一样的:double* p = ...; double** pp = &p; /* fine */; double a[3]; double (*pa)[3] = &a; /* fine */; pp = &a; /* differing pointer types! */ pa = &p; /* differing pointer types */
  • 问题是如何从 C# 调用它

标签: c# c++ c marshalling


【解决方案1】:

如果您已经有一个 C++/CLI 包装器,我会在那里调整 API 并制作一个更多的 C#-ish。

因此,将 C++/CLI 声明更改为:

int MyFunc(array<double>^ points,
            array<double>^ parameters);

然后在该实现中执行所有托管->非托管包装。

最后,它看起来像这样:

int MyFunc(array<double>^ points,
    array<double>^ parameters)
{

    if (points->Length != 3)
    {
        throw gcnew System::ArgumentOutOfRangeException("Expecting exactly 3 points");
    }

    double *pPoints = (double*)alloca(sizeof(double) * points->Length);

    for (int i = 0; i < points->Length; i++)
    {
        pPoints[i] = points[i];
    }

    double* pParams = (double*)alloca(sizeof(double) * parameters->Length);

    for (int i = 0; i < parameters->Length; i++)
    {
        pParams[i] = parameters[i];
    }

    double(*pPoints3)[3] = (double(*)[3])pPoints;
    int numParams = parameters->Length;
    my_func(pPoints3, pParams, &numParams);
}

但是,我完全混淆了 ???因为我不完全知道const double(*pPoints3)[3] 是什么意思。 3个双打的数组?还是指向双精度的指针数组?

【讨论】:

  • 谢谢,这可能是一种方法。尽管将 array^ 从 C++ 转换为 C 中的 double(*points)[3],但我仍然遇到问题。您能否更具体一些?
  • @Sorin-AlexandruCristescu 我已经扩展了答案,但是我坚持第一个论点。您是否有可能查看 C 代码以了解该参数实际上是什么?
  • 它是一个指向数组的指针;数组中的每一项都是一个三元组: c = malloc(sizeof(double[3]) * size);然后,这个“c”包含三元组,例如(1、2、3)、(4、5、6)等
  • 那么也许这样是正确的,但我不确定。您可能必须将其作为分段数组处理。
  • 正确,谢谢。我本来希望能够从 C# 传递一个参数,该参数将简单地转换为 C/C++ 中的 double(*pPoints)[3],但这对我来说已经足够了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-17
  • 1970-01-01
  • 2012-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多