0

概括:

我有一堆必须从 C# 调用的 C 函数。我目前的工作解决方案基于函数重载,我想知道是否有更优雅的解决方案。

C的东西:

头文件中的某处

typedef struct _unknown_stuff * handle; // a opaque pointer

函数示例

func( uint      num_entries,
      handle *  objects,
      uint *    n)
{ ... }

在 C 中,该函数的使用应与此类似:

// warning: i bet that the syntax is not correct but you should get the idea...

uint n;

func(0, null, &n);

handle * objects = malloc(n * sizeof(handle));

func(n, objects, null);

C# 的东西:

现在我在 C# 中执行以下操作:

public struct handle
{
    public IntPtr Pointer;
}

// version to get number of objects
[DllImport(dll, ...]
private static extern void
func(  uint        must_be_zero,
       object      must_be_null,
       out uint    n);

// version to get the actual data
[DllImport(dll, ...]
private static extern void
func(   uint           num_entries,
        [Out] handle[] objects,
        int            must_be_zero);

接着:

handle[] objects;

uint n = 42;

func(0, null, out n);

objects = new handle[n];

func(n, objects, 0);

问题

由于我是 C# 菜鸟,我想知道这是否是最好的方法。特别是我想知道是否有办法重载函数。

4

2 回答 2

1

首先,您的代码原样是错误的,因为在第二个 C# 签名中,您的第三个参数是int,而相应的 C 参数仍然是int*。它在针对 32 位 Windows 时会起作用,因为sizeof(int)==sizeof(int*)在那里——所以当你传递一个 0 int 时,你最终会传递一个空指针——但它不是 64 位安全的。如果你仍然想那样做,你需要在IntPtr那里使用。

除此之外,您可以尝试:

[DllImport(dll, ...]
private static extern void func(
  uint num_entries,
  [Out] handle[] objects,
  [Out] int[] num_devices);

使第三个参数成为一个数组,以便您可以在那里传递 null 。

或者只是使用指针。没有什么不好的,不要害怕unsafe关键字——任何类型的 P/Invoke 本质上都是不安全的,所以你最好明确一点。

于 2009-06-10T18:37:46.040 回答
0

C dll不会看0,并将其处理为null吗?

它只有一个功能,对吗?也就是说,C 函数被定义一次,而不是为 null 情况单独定义,并且将有一个

if( objects == NULL )
检查那里的某个地方。在大多数系统上(检查目标系统的 stdio.h),这是 0。因此,从 pinvoke 调用这个位置的值为 0 应该会执行您想要重载的操作。

于 2009-06-10T18:38:29.003 回答