我目前正在.Net
中包装Un4seen BASS音频库 BASS函数返回bool
值,需要检查LastError
以了解返回false时发生的错误。
所以我实现了一个Return<T>
类来使它面向对象:
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<bool>
,以便用户可以轻松地以面向对象的方式检查ErrorCode
。
现在,您可以说我创建了另一种方法,如:
// bool implicitly converts to Return<bool>
public static Return<bool> StreamFree2(int Handle) => StreamFree(Handle)
但是,问题在于已经存在数千个DllImports并且为所有这些进行此操作将是一场噩梦。
所以,我试过了:
[DllImport(DllName, EntryPoint = "BASS_StreamFree")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern Return<bool> StreamFree(int Handle);
它汇编了,但根本没有用。
任何人都可以请指出我错在哪里或者甚至是这样的事情。
先谢谢。
答案 0 :(得分:2)
如果没有编写包装函数,则无法执行此操作。您不能简单地更改函数的返回类型。编组程序无法自动创建新的Return<T>
对象。您对声明的最后尝试告诉编组器该函数返回BOOL
,但该函数未声明为返回BOOL
。显然这不起作用;当检测到不匹配时,它在运行时失败。
可能还有另一个问题。我不知道BASS库函数实际返回的是什么类型,但如果它是bool
,那么UnmanagedType.Bool
是错误的类型。你真的想要UnmanagedType.U1
。 UnmanagedType.Bool
指的是4字节BOOL
类型,实际上是一个整数。 UnmanagedType.U1
指的是C ++的1字节bool
类型。
更一般地说,我不认为你的“面向对象”方法会提供任何真正的优势。当然,您将返回一个对象,但您编写的客户端代码看起来并没有什么不同,因为您每次都必须检查错误代码。
一个优雅的,符合.NET的设计会在库函数返回错误时抛出异常。然后该异常(BassException
或其他)将包装错误代码。当然,这需要为每个库函数编写包装器函数,但是一旦完成,至少会有一些回报。考虑使用工具自动生成此类函数。