Wil*_*ert 7 c# c++ pinvoke interop marshalling
我已经在这里和这里阅读了C++ Interop与P/Invoke的各种MSDN页面,但我仍然感到困惑.
我有一些大型的双打数组,我需要进入本机代码,以及一些需要返回的结果数组.我事先并不知道输出数组的大小.为简单起见,我将在示例中仅使用单个数组.该平台是x64; 我读到在32位和64位环境之间编组内部是完全不同的,所以这可能很重要.
C#
[DllImport("NativeLib.dll")]
public static extern void ComputeSomething(double[] inputs, int inlen,
[Out] out IntPtr outputs, [Out] out int outlen);
[DllImport("NativeLib.dll")]
public static extern void FreeArray(IntPtr outputs);
public void Compute(double[] inputs, out double[] outputs)
{
IntPtr output_ptr;
int outlen;
ComputeSomething(inputs, inputs.Length, out output_ptr, out outlen);
outputs = new double[outlen];
Marshal.Copy(output_ptr, outputs, 0, outlen);
FreeArray(output_ptr);
}
Run Code Online (Sandbox Code Playgroud)
C++
extern "C"
{
void ComputeSomething(double* inputs, int input_length,
double** outputs, int* output_length)
{
//...
*output_length = ...;
*outputs = new double[output_length];
//...
}
void FreeArray(double* outputs)
{
delete[] outputs;
}
}
Run Code Online (Sandbox Code Playgroud)
它有效,也就是说,我可以读出我在C++端写入数组的双打.不过,我想知道:
请注意,我们有一个可用的C++/Cli版本,但是在第三方库代码中存在与导致崩溃的本地静态有关的一些问题.微软将此问题标记为WONTFIX,这就是我寻找替代品的原因.
没关系.完全没有返回错误代码的方法非常糟糕,当数组很大并且程序内存不足时会受到伤害.你得到的严重崩溃是非常不可知的.
复制数组并明确释放它们的需要当然不会赢得任何奖项.您可以通过让调用者将指针传递给自己的数组来解决这个问题,然后编写元素.但是,您需要一个协议让调用者确定数组需要多大,这需要调用该方法两次.第一个调用返回所需的大小,第二个调用完成工作.
样板示例如下:
[DllImport("foo.dll")]
private static int ReturnData(double[] data, ref int dataLength);
Run Code Online (Sandbox Code Playgroud)
以及样本用法:
int len = 0;
double[] data = null;
int err = ReturnData(data, ref len);
if (err == ERROR_MORE_DATA) { // NOTE: expected
data = new double[len];
err = ReturnData(data, len);
}
Run Code Online (Sandbox Code Playgroud)
无需复制,无需释放内存,好事.如果本地代码没有注意传递的len,那么本机代码可能会损坏GC堆,这不是一件好事.但当然容易避免.
如果将确定输出长度的代码与填充输出的代码分开是可行的,那么您可以:
但我假设您已拒绝此选项,因为它不切实际。在这种情况下,您的代码是解决您的问题的完全合理的方法。事实上我想说你做得非常好。
一旦修复了调用约定不匹配的问题,代码将在 x86 中正常工作。在 C++ 方面,调用约定是cdecl,但在 C# 方面是stdcall。这在 x64 上并不重要,因为只有一种调用约定。但在 x86 下就会出现问题。
一些评论:
[Out]以及out。后者暗示着前者。CoTaskMemAlloc在 C++ 端,然后Mashal.FreeCoTaskMem在 C# 端取消分配。| 归档时间: |
|
| 查看次数: |
1683 次 |
| 最近记录: |