生成的 COM 方法在参数上缺少 'out' 关键字
Generated COM method lacks 'out' keyword on a parameter
我正在尝试使用 C# 中的 Image Mastering API,但某些方法缺少 out
关键字,因此无法执行。
我通过执行以下操作生成了互操作代码:
- 引用,添加引用
- COM,类型库
- Microsoft IMAPI2 基本功能
在我撞墙之前它一直工作正常,这是我目前使用的代码:
using System;
using IMAPI2;
namespace ConsoleApp1
{
internal static class Program
{
private static void Main(string[] args)
{
var master2 = new MsftDiscMaster2();
var recorder2 = new MsftDiscRecorder2();
var recorderUniqueId = master2[0];
Console.WriteLine(recorderUniqueId);
recorder2.InitializeDiscRecorder(recorderUniqueId);
var recorder2Ex = (IDiscRecorder2Ex)recorder2;
// this fails as pointer should be an 'out' parameter
// System.NullReferenceException: 'Object reference not set to an instance of an object.'
var discInformation = new IntPtr();
recorder2Ex.GetDiscInformation(discInformation, out var byteSize);
}
}
}
IDiscRecorder2Ex::GetDiscInformation的原始签名:
HRESULT GetDiscInformation(
[out] BYTE **discInformation,
[out] ULONG_IMAPI2_DISC_INFORMATION *byteSize
);
Visual Studio生成的签名:
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetDiscInformation([Out] IntPtr discInformation, out uint byteSize);
我想手动编写接口代码是可行的,但这是一项艰巨的任务...
问题:
有没有办法让 Visual Studio 生成正确的签名?
此函数旨在 return 一个指向数组的指针和一个大小,并且这两个结果都通过 out
参数获得。 discInformation
参数是双重间接的:它指向一个存储指针的位置,该指针指向正在 returned 的数组的开头。
从技术上讲,我认为这可以翻译为
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetDiscInformation(
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out byte[] discInformation,
[Out] out uint byteSize);
那你就可以了
GetDiscInformation(out var discInformation, out var byteSize);
但是,类型库转换器并没有这样做。所以你需要自己编组数组。看起来您根本没有正确执行此操作。 :
byte[] discInformation;
unsafe
{
var di = new IntPtr();
recorder2Ex.GetDiscInformation((IntPtr)&di, out var byteSize);
discInformation = new byte[byteSize];
Marshal.Copy(di, discInformation, 0, byteSize);
}
我正在尝试使用 C# 中的 Image Mastering API,但某些方法缺少 out
关键字,因此无法执行。
我通过执行以下操作生成了互操作代码:
- 引用,添加引用
- COM,类型库
- Microsoft IMAPI2 基本功能
在我撞墙之前它一直工作正常,这是我目前使用的代码:
using System;
using IMAPI2;
namespace ConsoleApp1
{
internal static class Program
{
private static void Main(string[] args)
{
var master2 = new MsftDiscMaster2();
var recorder2 = new MsftDiscRecorder2();
var recorderUniqueId = master2[0];
Console.WriteLine(recorderUniqueId);
recorder2.InitializeDiscRecorder(recorderUniqueId);
var recorder2Ex = (IDiscRecorder2Ex)recorder2;
// this fails as pointer should be an 'out' parameter
// System.NullReferenceException: 'Object reference not set to an instance of an object.'
var discInformation = new IntPtr();
recorder2Ex.GetDiscInformation(discInformation, out var byteSize);
}
}
}
IDiscRecorder2Ex::GetDiscInformation的原始签名:
HRESULT GetDiscInformation(
[out] BYTE **discInformation,
[out] ULONG_IMAPI2_DISC_INFORMATION *byteSize
);
Visual Studio生成的签名:
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetDiscInformation([Out] IntPtr discInformation, out uint byteSize);
我想手动编写接口代码是可行的,但这是一项艰巨的任务...
问题:
有没有办法让 Visual Studio 生成正确的签名?
此函数旨在 return 一个指向数组的指针和一个大小,并且这两个结果都通过 out
参数获得。 discInformation
参数是双重间接的:它指向一个存储指针的位置,该指针指向正在 returned 的数组的开头。
从技术上讲,我认为这可以翻译为
[MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
void GetDiscInformation(
[Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out byte[] discInformation,
[Out] out uint byteSize);
那你就可以了
GetDiscInformation(out var discInformation, out var byteSize);
但是,类型库转换器并没有这样做。所以你需要自己编组数组。看起来您根本没有正确执行此操作。 :
byte[] discInformation;
unsafe
{
var di = new IntPtr();
recorder2Ex.GetDiscInformation((IntPtr)&di, out var byteSize);
discInformation = new byte[byteSize];
Marshal.Copy(di, discInformation, 0, byteSize);
}