要点:
我有一堆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,我想知道这是否是最好的方法。特别是我想知道是否有一种方法可以重载函数。
答案 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应该做你想重载的事情。