【问题标题】:Generated COM method lacks 'out' keyword on a parameter生成的 COM 方法在参数上缺少“out”关键字
【发布时间】:2022-01-25 21:49:23
【问题描述】:

我正在尝试使用 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 生成正确的签名?

【问题讨论】:

  • out uint byteSize 对于该签名看起来是正确的。您需要为discInformation 传递指向IntPtr 变量的指针,该变量将接收指向数组的指针,数组的大小在byteSize 中接收。换句话说,你需要做类似unsafe { GetDiscInformation(&discInformation, out byteSize); }
  • 效果非常好,请发布答案,以便我接受并为您投票:)

标签: c# com interop


【解决方案1】:

此函数旨在返回指向数组的指针和大小,这两个结果都来自out 参数。 discInformation 参数是双向间接的:它指向一个存储指向要返回的数组开头的指针的位置。

从技术上讲,我认为这可以翻译为

[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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-10
    • 1970-01-01
    • 2018-07-26
    • 2017-11-30
    • 1970-01-01
    相关资源
    最近更新 更多