复杂(?)pinvoke情况 - 避免函数重载

时间:2009-06-10 18:24:17

标签: c# pinvoke dllimport

要点:

我有一堆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#noob,我想知道这是否是最好的方法。特别是我想知道是否有一种方法可以重载函数。

2 个答案:

答案 0 :(得分: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本质上都是不安全的,所以你也可以明确地说明它。

答案 1 :(得分:0)

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

它只有一个功能,对吗?也就是说,C函数定义一次,而不是单独定义为null的情况,并且在那里的某处会进行

if( objects == NULL )
检查。在大多数系统上(检查目标系统的stdio.h),这是0。 所以在这个地方调用带有0值的pinvoke应该做你想重载的事情。