none
返却されたパラメータが一次元になる。 RRS feed

  • 質問

  • VB2005EXEからVC++2005DLLを呼び出す簡単なサンプルPG

    を作成しました。

    パラメータは、型がSHORTとINTEGERの配列です。

    VB2005EXEからCALLして、VC2005DLLで値をセットし、

    返却されると、一次元配列になってしまいます。

    何が問題でしょうか?


    <VB2005ソース>

    Public Declare Function test Lib "sentakdg.dll" ( _
            ByRef rireki_ymd As Short, _
            ByRef mascd As Integer) As Integer


    Public Sub sentakdg_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles sentakdg.Click
      
            Dim rireki_ymd(49, 2) As Short
            Dim mascd(3, 1) As Integer

            Try
                test( _
                rireki_ymd(0, 0), _
                mascd(0, 0))


            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
      
    End Sub


    <VC++2005ソース>

    __declspec(dllexport) short __stdcall test(       short rireki_ymd[50][3],
               int   macd[4][2])

     int ii;
     int kk;

        for (ii = 0; ii < 50; ii++)
        {
            for (kk = 0; kk < 3; kk++)
            {
                rireki_ymd[ii][kk] = ii * kk;
            }
        }
        for (ii = 0; ii < 4; ii++)
        {
            for (kk = 0; kk < 2; kk++)
            {
                macd[ii][kk] = ii * kk;
            }
        }

     return(12);

     

    2006年11月15日 2:14

すべての返信

  • 配列の構造が、VBとは違うのではないでしょうか?
    VCの配列は単に連続したメモリなだけですし。

    参考:配列に対する既定のマーシャリング 

    2006年11月15日 2:55
  • 端的に言うと仕様です。

    マーシャリングの際、C スタイルの配列は強制的に 1 次元配列とみなされてマーシャリングされます。詳しくは MSDN で 「配列に対する既定のマーシャリング」「さまざまな型の配列のマーシャリング」辺りの記事をご覧ください。

    .NET 側では各次元の要素数の積だけの要素数を持った 1 次元配列を使用することになります。

    それはそうと、Declare ステートメントで配列をパラメータに宣言するなら、ByRef As 型 よりも ByVal As 型() の方が良いでしょう。.NET では配列の先頭からメモリ上正しく並んでいるという保証はありませんから(配列で宣言しておけばフレームワークがうまいことやってくれます)。

    // というか ByRef As 型 が使えることにびっくり。

    2006年11月15日 3:05
  • 蒼の洞窟さん、Hongliangさんありがとうございます。

    >端的に言うと仕様です。

    すいません。添付したサンプルは、一つ一つをパラメータで渡すやり方ですが、
    この方法では、VB側で受け取ると次元が、2次元で正しく返却されました。
    問題なのは、この2つのパラメータを、構造体で定義し、

    <StructLayout(LayoutKind.Sequential)> _
    Public Structure information
      <MarshalAs(UnmanagedType.ByValArray, sizeconst:=150)> Dim rireki_ymd(, ) As Short
            <MarshalAs(UnmanagedType.ByValArray, sizeconst:=8)> Dim mascd(, ) As Integer
     Public Sub Initialize()
                ReDim rireki_ymd(49, 2)
                ReDim mascd(3, 1)
            End Sub
    End Structure

    構造体渡しにすると、VB2005EXEに返却された場合、1次元となってしまいます。
    これについても仕様ということでしょうか?


    >// というか ByRef As 型 が使えることにびっくり。
    →特に問題なく使用できました。値渡し(BYVAL)の方がいいのですね。

    それから少しアドバイスをいただきたいのですが、
    例えば下記のような、構造体を、VB2005EXEから、VC2005DLLに渡したいのですが、
    1次元になってしまうこと考慮した場合、
    構造体渡しをやめてパラメータ4つで渡す方法しかないでしょうか?
    また、構造体自体を配列にして渡す場合はどうでしょうか?

    <StructLayout(LayoutKind.Sequential)> _
    Public Structure information
            Dim name As String
            Dim age(,) As Integer
            Dim sex(,) As Byte
            Dim sh(,,) As Short
    End Structure

    2006年11月16日 1:47