您可以使用 将 PInvoke 方法保持为私有UIntPtr
,并使用您喜欢的签名实现另一种方法,该方法调用 PInvoke 正确映射所有内容,并且这个方法将是公共的:
/// Return Type: size_t->unsigned int
///bgr: uint8_t*
///width: int
///height: int
///stride: int
///output: uint8_t**
public static ulong WebPEncodeLosslessBGR([InAttribute()] IntPtr bgr, int width, int height, int stride, ref IntPtr output)
{
return (ulong)_WebPEncodeLosslessBGR(bgr, width, height, stride, ref output);
}
[DllImportAttribute("libwebp.dll", EntryPoint = "WebPEncodeLosslessBGR")]
[return: MarshalAsAttribute(UnmanagedType.SysUInt)]
private static extern UIntPtr _WebPEncodeLosslessBGR([InAttribute()] IntPtr bgr, int width, int height, int stride, ref IntPtr output);
当框架变得难以处理时......不要使用它们。编组是一种痛苦,我倾向于只使用我已经知道的东西......其他一切,我只是四处走动。
编辑
它不起作用,因为编组器不够聪明,无法看到每种SysUInt
类型都适合一种ulong
类型。它正在检查返回,与参数相同。
确实,您不能将ulong
andSysUInt
用作参数,但您可以将其用作 return ... 看到差异并不聪明。=\
有哪些选择?
UIntPtr
似乎是最好的选择......但还有其他选择:实现自定义编组器,使用接口ICustomMarshaler
......并使用UnmanagedType.CustomMarshaler
:
[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(CustomMarshalerType))]
ICustomMarshaler 实现
使用 ICustomMarshaler 的这个实现,您可以做您想做的事。我没有测试它,因为我没有一个非托管库来进行测试,但它很简单,而且非常简单......所以我认为它会按原样工作,无需任何更改。如果没有,请发表评论,我会修改它。
public class CustomMarshalerType : ICustomMarshaler
{
public object MarshalNativeToManaged(IntPtr pNativeData)
{
return (ulong)Marshal.ReadIntPtr(pNativeData).ToInt64();
}
public IntPtr MarshalManagedToNative(object ManagedObj)
{
throw new InvalidOperationException();
}
public void CleanUpNativeData(IntPtr pNativeData)
{
}
public void CleanUpManagedData(object ManagedObj)
{
}
public int GetNativeDataSize()
{
return IntPtr.Size;
}
}