C# 调用DLL中的函数时会发生什么 我使用的是从C++代码编译的DLL,从我的C代码看。我使用API构建了一个线性规划模型,然后对其进行求解。我调用以下函数: [DllImport("lpsolve55.dll", SetLastError = true)] public static extern bool add_columnex (int lp, int count, double[] column, int[] rowno);

C# 调用DLL中的函数时会发生什么 我使用的是从C++代码编译的DLL,从我的C代码看。我使用API构建了一个线性规划模型,然后对其进行求解。我调用以下函数: [DllImport("lpsolve55.dll", SetLastError = true)] public static extern bool add_columnex (int lp, int count, double[] column, int[] rowno);,c#,c++,memory,C#,C++,Memory,memorywise,我想知道当我调用这样一个函数时会发生什么,我在托管代码中创建的int和数组会在c代码中留下作用域。他们有资格接受垃圾收集吗?这对C++代码意味着什么?或者是不合格的,在这种情况下:为什么?因为函数原型使用的是普通的旧数据类型和数组,这些值的内存固定在适当的位置,然后本机代码直接作用于数据。然后,当函数返回时,内存被取消固定,可以进行垃圾回收 换句话说,他们永远不会离开这个范围 在C++代码中,如果需要存储任何数据,那么它将需要将传入的数据拷贝到其中,然后管理该内存本身。<

memorywise,我想知道当我调用这样一个函数时会发生什么,我在托管代码中创建的int和数组会在c代码中留下作用域。他们有资格接受垃圾收集吗?这对C++代码意味着什么?或者是不合格的,在这种情况下:为什么?

因为函数原型使用的是普通的旧数据类型和数组,这些值的内存固定在适当的位置,然后本机代码直接作用于数据。然后,当函数返回时,内存被取消固定,可以进行垃圾回收

换句话说,他们永远不会离开这个范围


在C++代码中,如果需要存储任何数据,那么它将需要将传入的数据拷贝到其中,然后管理该内存本身。

< P>因为函数原型使用的是普通的旧数据类型和数组,这些值的内存被固定在适当位置,然后本机代码直接作用于数据。然后,当函数返回时,内存被取消固定,可以进行垃圾回收

换句话说,他们永远不会离开这个范围


< C++代码>如果它需要存储任何数据,那么它将需要获取传递到其中的数据的副本,然后管理内存本身。

如果你的应用程序在经过垃圾收集一段时间后没有因AccessViolationException而崩溃,那么可以很安全地假设非托管代码复制了你需要的数组元素通过了。这是正常的事情,否则库也很难从本机代码中使用。还应该有一个API函数,允许您清除或重新初始化模型,这应该是释放内存。

如果你的应用程序在经过垃圾收集一段时间后没有因AccessViolationException而崩溃,那么可以很安全地假设非托管代码是你传递给它的数组元素的副本。这是正常的事情,否则库也很难从本机代码中使用。还应该有一个API函数,允许您清除或重新初始化模型,应该释放内存。

我认为Nick已经介绍了基本部分,这只是为了添加更多信息。int/double数组被视为在托管/非托管世界中具有相同布局的可blittable类型-这些类型通常在封送时被固定。所以你不必担心GC。另外,您所做的操作表明按值传递数组-在这种情况下,封送处理程序将其视为in参数-如果您的非托管dll将更新数组中的值,那么我建议您将其标记为in/Out参数,例如[in,Out]double[]列。有关更多信息:

可飞航和不可飞航类型: 复制和固定: 编组数组:
我认为Nick已经介绍了基本部分,这只是为了补充更多信息。int/double数组被视为在托管/非托管世界中具有相同布局的可blittable类型-这些类型通常在封送时被固定。所以你不必担心GC。另外,您所做的操作表明按值传递数组-在这种情况下,封送处理程序将其视为in参数-如果您的非托管dll将更新数组中的值,那么我建议您将其标记为in/Out参数,例如[in,Out]double[]列。有关更多信息:

可飞航和不可飞航类型: 复制和固定: 编组数组:

C或C++函数有这样的原型:

 bool add_columnex(int lp, int count, double[] column, int[] rowno);
参数lp和count按值传递。参数column和rowno也通过值传递,但实际数据通过引用传递,函数add_columnex必须取消对column和rowno的引用。此取消引用仅在函数调用期间允许。当函数返回时,这些参数超出范围。取消引用的类型必须在接口的合同中


当函数返回时,所有参数都超出范围,这并不意味着函数在调用后可以执行任何操作。如果函数存储参数的副本,即double或rowno数组的地址,则契约必须允许这样做。那样的话,你会有麻烦的。一个更好的契约是函数必须复制撤销的数据。

< P> C或C++函数有这样的原型:

 bool add_columnex(int lp, int count, double[] column, int[] rowno);
参数lp和count按值传递。参数column和rowno也通过值传递,但实际数据通过引用传递,函数add_columnex必须取消对column和rowno的引用。此取消引用仅在函数调用期间允许。当函数返回时,这些参数超出范围。取消引用的类型必须在接口的合同中

< p> 当函数返回时,所有参数都超出范围,这并不意味着函数在调用后可以执行任何操作。如果函数存储参数的副本,即double或rowno数组的地址,则契约必须允许这样做。那样的话,你会有麻烦的。更好的约定是函数必须复制解引用的数据