我有一个 C++ dll 文件,其中包含一个名为 fn(double* p, int* pLength)
的导出函数,其中,p
是一个指针(是一个输出C#中使用的array), pLength
在此函数中计算的是p的长度(size)。代码在这里:
void _stdcall fn(double* p, int* pLength)
{
int i=0;
double p_=0;
do
{
p[i]=p_;
p_=an expression!!!!!;
i++;
}
while (condition with p_); //Condition of loop
*pLength=i;
return;
}
我成功编译成dll文件。此文件名为“testFile.dll”并将其移至 System32 文件夹。
现在,我启动 C# 控制台项目并声明从“testFile.dll”导出的函数 fn()
,此代码为:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
[DllImport("testFile.dll")]
public static extern void fn(double[] p, ref int pLength);
static void Main(string[] args)
{
// I want to declare an array with unknown length (size),
// because the length is calculated from fn() function!!!
// And pass to fn() function to get p[i].....
double[] p;
int pLength;
fn(p, ref pLength);
// Display pLength and p[i]
Console.WriteLine(pLength);
for (int i = 0; i < pLength; i++)
Console.WriteLine(p[i]);
Console.ReadKey();
}
}
}
我运行并得到两个错误:
Error 1 Use of unassigned local variable 'p'
Error 2 Use of unassigned local variable 'pLength'
如何修复它们?,我想从 fn()
“testFile.dll”中的函数。提前致谢。
最佳答案
据我了解,您需要调用该函数两次。一旦你将传递一个空数组并要求函数计算所需的长度。然后您再次调用分配的数组,该函数将填充该数组。
非托管代码可能如下所示:
void __stdcall fn(double p[], int* pLength)
{
int i = 0;
double p_ = 0;
do
{
if (p) p[i] = p_;
p_ = ...;
i++;
}
while (...);
*pLength = i;
}
请注意,代码会检查 p
是否已分配,如果已分配,则只写入数组。
在托管端,代码如下所示:
[DllImport(...)]
public static extern void fn(double[] p, out int pLength);
....
int pLength;
fn(null, out pLength);
double[] p = new double[pLength];
fn(p, out pLength);
一个更安全的版本是将数组的长度传递给函数。这将允许该函数确保它不会注销结尾。
void __stdcall fn(double p[], int* pLength)
{
int i = 0;
double p_ = 0;
do
{
if (p)
{
if (i >= *pLength) return -1; // or some other error code
p[i] = p_;
}
p_ = ...;
i++;
}
while (...);
*pLength = i;
}
管理端:
[DllImport(...)]
public static extern void fn(double[] p, ref int pLength);
....
int pLength = 0;
fn(null, ref pLength);
double[] p = new double[pLength];
fn(p, ref pLength);
如果您只想调用该函数一次,则需要执行以下操作:
- 在非托管代码中动态分配内存。使用
GlobalAlloc
以便托管代码可以释放它。 - 如果您的初始分配被证明长度不足,请准备好在非托管代码中重新分配。
- 在托管代码中使用
IntPtr
类型的out
参数获取指向非托管内存的指针。 - 使用
Marshal.Copy
将数组内容复制到您的托管double[]
对象中。 - 调用
Marshal.FreeHGlobal
释放非托管内存。
这项技术要复杂得多,涉及更多的样板文件。只有在我概述的第一种方法中存在显着性能开销时,您才采用这种方法。
旁白。请不要将您的文件放在系统目录中。它属于系统,您不应修改它。将 DLL 放在与主机可执行文件相同的目录中。
关于c# - 如何从 C++ dll 在 C# 函数中传递大小未知的数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22753557/