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

まず、コードは間違っています。2番目のC#署名では、3番目の引数はですがint、対応するC引数はまだint*です。32ビットWindowsをターゲットにする場合は機能しsizeof(int)==sizeof(int*)ます。これは、0 intを渡すと、nullポインターを渡すことになりますが、64ビットでは安全ではないためです。それでもそのようにしたい場合は、そこで使用する必要がIntPtrあります。

それとは別に、あなたは試すことができます:

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

3番目の引数を配列にして、そこにnullを渡すことができるようにします。

または、ポインタを使用します。それについて悪いことは何もありません、そしてunsafeキーワードを恐れないでください-とにかくどんな種類のP / Invokeも本質的に安全ではないので、あなたはそれについて明示したほうがよいでしょう。

于 2009-06-10T18:37:46.040 に答える
0

C dllは0を見て、それをnullとして処理しませんか?

機能は1つだけですよね?つまり、C関数は1回定義され、nullの場合は個別に定義されず、次のようになります。

if( objects == NULL )
どこかをチェックしてください。ほとんどのシステム(ターゲットシステムのstdio.hを確認してください)では、これは0です。したがって、この場所で値が0のpinvokeから呼び出すと、オーバーロードで実行したいことを実行できます。

于 2009-06-10T18:38:29.003 に答える