0

ネイティブ C++ dll を呼び出す C# プログラムがあります。

C# には次の構造体があります。

[StructLayout(LayoutKind.Sequential)]
public struct Phenomenon
{
    [MarshalAs(UnmanagedType.U1)] public char Type;
    [MarshalAs(UnmanagedType.R8)] public double Jd;
    [MarshalAs(UnmanagedType.R8)] public double Loc_jd;
    [MarshalAs(UnmanagedType.R8)] public double Angle;
    [MarshalAs(UnmanagedType.U1)] public char Tran_dir;
    [MarshalAs(UnmanagedType.I2)] public Int16 Warning;
}

C++ プログラムには、次の構造体定義があります。

   typedef struct
   {
      char type;
      double jd;
      double loc_jd;
      double angle;
      char tran_dir;
      short int warning;
   } phenomenon;

C# プログラムは Phenomenom オブジェクトをインスタンス化し、C++ メソッドへの次の呼び出しを行います。

Phenomenon[] phenomena = new Phenomenon[6];
short status = rsttwi_temp(phenomena);

C++ は単純に構造体を更新して戻ります。C++ 関数は次のとおりです。

__declspec(dllexport) short int rsttwi_temp (phenomenon phen[1])
{
    phen[0].type = 'Z';
    phen[0].jd = 1.1;
    phen[0].loc_jd = 2.2;
    phen[0].angle = 3.3;
    phen[0].tran_dir = 4.4;
    phen[0].warning = '0';

    return 0;
}

C++ 関数の呼び出し後に構造体の値を出力すると、C# プログラムから、構造体が更新されていません (つまり、C++ 関数が呼び出される前と同じです)。C++ プログラムは値を確認して更新できるようですが、戻り時に C# が構造体の値の更新を確認することはありません。値と参照の問題だと思って、構造体ではなく、C# プログラムのクラスでこれを実行しようとさえしました。まだ運がありません。

質問: 呼び出された C++ 関数が、渡された実際の構造体を更新できるようにするには、どのようなマーシャリングが必要ですか?

ありがとうございました。-グレッグ・エドワーズ・トータル・イマージョン・ソフトウェア

4

3 に答える 3

1

このように使用すると動作します:

C++

 __declspec(dllexport) short int rsttwi_temp (phenomenon* phen)
{
    phen->jd = 1.1;
    phen->loc_jd = 2.2;
    phen->angle = 3.3;
    phen->warning = 0;
    return 0;
}

typedef struct
       {
          double jd;
          double loc_jd;
          double angle;
          short int warning;
       } phenomenon;

C#

[DllImport("somedll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern Int16 rsttwi_temp(ref Phenomenon value);

[StructLayout(LayoutKind.Sequential)]
        public struct Phenomenon
        {
            [MarshalAs(UnmanagedType.R8)]
            public double Jd;
            [MarshalAs(UnmanagedType.R8)]
            public double Loc_jd;
            [MarshalAs(UnmanagedType.R8)]
            public double Angle;
            [MarshalAs(UnmanagedType.I2)]
            public Int16 Warning;
        }

C# 呼び出し

 Phenomenon phenomena = new Phenomenon();
 short status = rsttwi_temp(ref phenomena);
于 2010-12-24T20:18:47.533 に答える