为什么我不能在固定语句中使用 extern 函数?

Why I cannot use extern functions in fixed statement?

提问人:a11ex 提问时间:11/9/2023 更新时间:11/9/2023 访问量:42

问:

我正在学习如何在 C# 中使用非托管代码,因此我尝试使用它制作一些控制台应用程序。我有一个外部库,里面有一个名为 fillArray 的函数,它返回一个 char 指针。当我尝试在固定语句中使用它时,出现错误“表达式不能在'固定'状态中使用”。

char[] array = new char[42];
        unsafe
        {
            char* a = FunctionsHolder.fillArray(array); // it works
            fixed (char* p = FunctionsHolder.fillArray(array)) // here i have an error
            {
               //a bunch of code
            }
        }
C# 函数 指针 DLL 不安全指针

评论

0赞 Charlieface 11/9/2023
“它返回一个字符指针”,您建议如何从 C# 端释放该指针?或者更确切地说:如果你已经有了数组,为什么要返回指向它的指针?

答:

3赞 Ben Voigt 11/9/2023 #1

该语句固定托管对象,以便您可以获得指向该对象的指针。 从 DLLImport 函数返回的指针不是托管对象(如果它来自传入的指针,则它可能是指向托管对象的指针),因此 .NET 运行时不知道如何固定它。fixed

在您的情况下,返回的指针可能指向 的中间位置。由于您信任 p/invoke 来固定和取消固定它,因此当您获得返回值时,数组可能已经移动并且返回指针毫无意义。array

您需要在整个过程中固定数组,以便有意义地使用指针。例如:

unsafe
{
  char* p;
  fixed (char* parray = &array[0]) // pins entire array
  {
    p = DllFunctions.findInArray(array, array.Length, sought);
    // safely use `p`
  }
  // must not use `p` because the array object it points to is no longer pinned
}

评论

0赞 Charlieface 11/9/2023
注意:如果数组仅在一次调用期间使用,则无需固定数组。无论如何,编组员都会固定它。同样可以说,该函数应该只是将偏移量返回到数组中,然后就不需要固定,如前所述。
1赞 Ben Voigt 11/9/2023
@Charlieface:是的,如果可以更改函数签名/合约以返回索引,则可以消除问题。我正在解决一个无法更改的现有函数的解决方案。