指针作为泛型类型参数

Mic*_*idt 1 c# generics unsafe void-pointers

我有一堆外部C函数在C#中成为这样的东西:

public extern static int clGetDeviceInfo(
    IntPtr device, 
    uint param_name, 
    IntPtr param_value_size, 
    void* param_value, 
    out IntPtr param_value_size_ret);
Run Code Online (Sandbox Code Playgroud)

因为有一堆看似相似的函数,我想创建一个读取这些C函数提供的数据的方法.这就是我的用途:

unsafe public static ErrorCode GetInfoString(
    IntPtr handle, uint property, 
    Func<IntPtr, uint, IntPtr, void*, IntPtr, int> infoFunc, 
    out string value)
{
    // reading logic
}
Run Code Online (Sandbox Code Playgroud)

我的问题是C#不允许我使用它void*作为泛型参数Func.有没有解决这个问题的方法?

我既不能改变外部C函数的签名也不能改变C#函数的签名(我正在使用库).

Eri*_*ert 5

我的问题是C#不允许我使用void*Func的泛型参数.有没有解决这个问题的方法?

是.使用您目前使用的IntPtr 任何地方void*.void*如果可以避免,请不要在C#中使用.

我无法更改我试图作为参数传递的函数的签名,因此无法工作.

当然可以.你有

public extern static int clGetDeviceInfo(
    IntPtr device, 
    uint param_name, 
    IntPtr param_value_size, 
    void* param_value, 
    out IntPtr param_value_size_ret);
Run Code Online (Sandbox Code Playgroud)

您无法更改它,因为它位于库中.精细.什么可以更改?您可以更改自己的代码.所以编写自己的代码!你是一名计算机程序员; 这就是你做的:

private static int MyClGetDeviceInfo(
    IntPtr device, 
    uint param_name, 
    IntPtr param_value_size, 
    IntPtr param_value, 
    out IntPtr param_value_size_ret)
{
  unsafe 
  {
    return clGetDeviceInfo(device, param_name, param_value_size,
      (void*)param_value, out param_value_size_ret);
  }
}
Run Code Online (Sandbox Code Playgroud)

在那里,现在你有一个方法,有一个你可以做出的签名Func.

  • @MichaelSchmidt:我不认为这个解决方案更"好".**如果可以避免,请不要在C#中使用`void*`**.传递原始指针在C#中不是惯用的; 当你与C库进行互操作时,尽可能多地将它们隐藏在`IntPtr'之后.更好:编写自定义互操作库,*比目前使用的*更好*.您希望捕获互操作层中操作的语义,而不是在整个地方暴露原始指针. (2认同)
  • @MichaelSchmidt:我已经用 C# 专业编程很长一段时间了,我在非测试生产代码中使用 `void*` 的次数是*零次*。仔细想想你在这里做什么;在 C# 中滥用指针类型会产生严重后果,因为您实际上禁用了内存和类型安全系统。您可能花费更多的时间来输入这个问题,而不是围绕所有非托管 API 实现一组更清晰的包装器;花点时间把事情做好,以后就会得到回报。 (2认同)