1

VC++6 で書かれた古い ocx (spectrograph.ocx) があります。これには、次のように定義された AppendDataX() というメソッドが含まれています。

afx_msg void AppendDataX(float FAR* data, long n, float xpos);

この古い ocx コントロールを使用して、新しい C#.NET win32 アプリケーションを作成しようとしています。次のコマンドを使用しました。

AxImp spectrograph.ocx

AxSPECTROGRAPHLib.dll を生成します。コントロールを (新しく作成した .dll を介して) IDE (SharpDevelop) にインポートし、他のコントロールと同様にフォームに追加できます。float[] を ocx メソッドの AppendDataX() に渡そうとするまでは、これまでのところ問題ありません。

        FileStream tw = new FileStream("XX-YY-ZZZZ.2011.01.10.15.52.00.spec", FileMode.Open);
        BinaryReader br = new BinaryReader(tw);
        int pixelCnt = br.ReadInt32();
        float[] wavelength = new float[pixelCnt];
        for (int i=0; i<pixelCnt; i++)
            wavelength[i] = br.ReadSingle();

        bool eof = false;
        float temp;
        float[] spectrum = new float[pixelCnt];
        while(!eof)
        {
            try
            {
                temp = br.ReadSingle();
                for (int i=0; i<pixelCnt; i++)
                    spectrum[i] = br.ReadSingle();

                spec.AppendDataX(spectrum, pixelCnt, temp);
            }
            catch(EndOfStreamException)
            {
                eof = true;
            }
        }
        tw.Close();

これにより、コンパイル中に次のエラーが生成されます。

Argument '1': cannot convert from 'float[]' to 'ref float' (CS1503)

MSIL 逆アセンブラーを使用して AxSPECTROGRAPHLib.il を生成したところ、次のようになりました。

  .method public hidebysig newslot virtual 
      instance void  AppendDataX(float32& data,
                                 int32 n,
                                 float32 xPos) cil managed
{
// Code size       35 (0x23)
.maxstack  8
IL_0000:  ldarg.0
IL_0001:  ldfld      class [SPECTROGRAPHLib]SPECTROGRAPHLib._DSpectrograph AxSPECTROGRAPHLib.AxSpectrograph::ocx
IL_0006:  brtrue.s   IL_0014

IL_0008:  ldstr      "AppendDataX"
IL_000d:  ldc.i4.0
IL_000e:  newobj     instance void [System.Windows.Forms]System.Windows.Forms.AxHost/InvalidActiveXStateException::.ctor(string,
                                                                                                                         valuetype [System.Windows.Forms]System.Windows.Forms.AxHost/ActiveXInvokeKind)
IL_0013:  throw

IL_0014:  ldarg.0
IL_0015:  ldfld      class [SPECTROGRAPHLib]SPECTROGRAPHLib._DSpectrograph AxSPECTROGRAPHLib.AxSpectrograph::ocx
IL_001a:  ldarg.1
IL_001b:  ldarg.2
IL_001c:  ldarg.3
IL_001d:  callvirt   instance void [SPECTROGRAPHLib]SPECTROGRAPHLib._DSpectrograph::AppendDataX(float32&,
                                                                                                int32,
                                                                                                float32)
IL_0022:  ret
} // end of method AxSpectrograph::AppendDataX

float[] から c# から vc6++ ocx へのマーシャリングを示す簡単な例を検索して検索してきましたが、まだうまくいく例は見つかりませんでした。誰かが私を正しい方向に導くのを手伝ってくれませんか...私は正しい軌道に乗っているように感じます。これは本当に難しいことではありませんが、これを数日間見た後、立ち往生しているように感じます.

4

3 に答える 3

1
afx_msg void AppendDataX(float FAR* data, long n, float xpos);

これは問題です。オートメーションと互換性のある関数シグネチャではありません。配列は SafeArray として渡す必要があり、関数は HRESULT を返す必要があります。現時点では、タイプ ライブラリのインポーターは、最初の引数が配列であると推測する方法はありません。単一の float 値へのポインターである可能性もあります。それが推測したものです、ref float。

ネイティブ コードを変更できない場合は、生成された相互運用ライブラリを技術的に編集し、署名を float[] を使用するように変更できます。あなたの分解は非常に奇妙ですが、これは前に見たことがありません。CLR は通常、相互運用ライブラリ内の関数の宣言から COM スタブを動的に生成します。あなたが投稿したものをどうやって手に入れたのか、本当の手がかりはありません。

技術的には、モジュール エクスポートをタイプ ライブラリに取得することは可能です。ただし、それはOCXではありません。ただし、Automation と互換性のない署名と IL スタブについては説明しています。その場合、タイプ ライブラリを使用するよりも、エクスポートされた関数を直接使用する小さな C++/CLI ref クラス ラッパーを作成する方が簡単な場合があります。pin_ptr<> を使用すると、配列を float* に簡単に変換できます。

于 2011-01-17T21:46:03.047 に答える
0

コントロールが文字通り最初の要素のアドレスを必要とする場合は、いつでもそれを固定してアドレスを返すことができます。

var handle=GCHandle.Alloc( spectrum, GCHandleType.Pinned );
unsafe
{
    float *val=(float *)handle.AddrOfPinnedObject();
    // here's the val to send to your object
}
handle.Free();
于 2011-01-17T21:09:42.180 に答える