元帅 bool return 作为自定义 Return<bool>

Marshal bool return as custom Return<bool>

我目前正在 .Net 中包装 Un4seen BASS 音频库

BASS 函数 returning bool 值,需要检查 LastError 以了解如果 returned 为 false 时发生的错误。

所以我实现了一个 Return<T> class 使其面向对象:

using ManagedBass.Dynamics;

namespace ManagedBass
{
    /// <summary>
    /// Wraps a Bass Error in a function return value
    /// </summary>
    /// <typeparam name="T">The Type of the function return value</typeparam>
    public class Return<T>
    {
        public Errors ErrorCode { get; }

        Return(T Value)
        {
            ErrorCode = Bass.LastError;
            this.Value = Value;
        }

        public T Value { get; }

        public static implicit operator T(Return<T> e) => e.Value;

        public static implicit operator Return<T>(T e) => new Return<T>(e);

        public bool Success => ErrorCode == Errors.OK;
    }
}

现在的方法如下:

[DllImport(DllName, EntryPoint = "BASS_StreamFree")]
public static extern bool StreamFree(int Handle);

我想 return 一个 Return<bool> 以便用户可以轻松地以面向对象的方式检查 ErrorCode

现在,您可能会说我创建了另一个方法,例如:

// bool implicitly converts to Return<bool>
public static Return<bool> StreamFree2(int Handle) => StreamFree(Handle)

但是,问题是已经有数以千计的 DllImport 并且对所有这些都执行此操作将是一场噩梦。

所以,我尝试了:

[DllImport(DllName, EntryPoint = "BASS_StreamFree")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern Return<bool> StreamFree(int Handle);

它编译了,但根本不起作用。

任何人都可以指出我错在哪里或者这样的事情是否可能。

提前致谢。

如果 编写包装函数,就无法做到这一点。您不能简单地更改函数的 return 类型。编组器将无法自动创建新的 Return<T> 对象。您最后一次声明尝试告诉编组器函数 return 是一个 BOOL,但该函数未声明为 return 一个 BOOL。显然那是行不通的;当检测到不匹配时,它在运行时失败。

可能还有其他问题。我不知道 BASS 库实际运行的是什么类型 return,但如果它是 bool,那么 UnmanagedType.Bool 就是错误的类型。你实际上想要UnmanagedType.U1UnmanagedType.Bool指的是4字节的BOOL类型,其实就是一个整数。 UnmanagedType.U1指C++的1字节bool类型。

更一般地说,我认为您的 "object-oriented" 方法不会提供任何真正的优势。当然,您会 returning 一个对象,但是您编写的客户端代码看起来不会有任何不同,因为您仍然需要每次检查错误代码。

当库函数 return 出错时,一个优雅的、符合 .NET 的设计会抛出异常。然后该异常(BassException 或其他)将包装错误代码。当然,这将需要为每个库函数编写包装函数,但至少完成后会有一些回报。考虑使用工具自动生成此类函数。