VC6で作ったDLL内の関数に、VB2005で構造体配列のアドレスを渡すには?


SQ  2007-01-28 23:27:16  No: 135049

VC6で作った関数をDLL化し、
それをVB2005で使用したいと思っております。

DllImportを使用しております。
Dll側の関数にint型の引数を値渡し参照渡しするのには問題はございませんでした。

しかし、構造体配列を参照渡しするとエラーが発生し終了してしまいます。
自分なりに調べていろいろとしているのですが、同じようなケースが見つからず、
四苦八苦しております。
おそらくは、構造体のメンバのマーシャリングあたりがおかしいのかと思っておりますが、どうもうまくいきません。
よろしければ、おかしいところをご指摘いただけませんでしょうか。

以下に、dll側(VC6)と呼び出し側(VB2005)のソース、エラーメッセージを記載いたします。

//  DLL側(VC6)  //

typedef struct config_tag{
  char  SrvIP1[32];
  char  SrvIP2[32];
  char  SrvPort[32];  
  char  SrvName1[32];
  char  SrvName2[32];
  int   nLogFlag;
  int   nTransPeriodic;
} config_str;

int __stdcall StructFunc2( config_tag *cnf_str);

int __stdcall StructFunc2( config_str *structure)
{
  char cbuf[5][32] = {"192.168.11.1",
             "192.168.11.2",
             "1234",
             "Server1",
             "Server2"
            };
  int ibuf[2] = {1,2};

  int i;

  for( i=0; i<5; i++)
  {

    strcpy(structure[i].SrvIP1, cbuf[0]);
    strcpy(structure[i].SrvIP2, cbuf[1]);
    strcpy(structure[i].SrvPort, cbuf[2]);
    strcpy(structure[i].SrvName1, cbuf[3]);
    strcpy(structure[i].SrvName2, cbuf[4]);
    structure[i].nLogFlag = ibuf[0];
    structure[i].nTransPeriodic = ibuf[1];
  }

  return MessageBox(NULL, "引数として渡された構造体 config_tag にセットしました。","DLL側",0);

}

//   呼び出し側(VB2005)

****  module *********************
<StructLayout(LayoutKind.Sequential)> _
Public Structure config_tag
    <VBFixedString(32), System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst:=32)> Public SrvIP1 As String
    <VBFixedString(32), System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst:=32)> Public SrvIP2 As String 
    <VBFixedString(32), System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst:=32)> Public SrvPort As String
    <VBFixedString(32), System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst:=32)> Public SrvName1 As String
    <VBFixedString(32), System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst:=32)> Public SrvName2 As String
    Public nLogFlag As Integer
    Public nTransPeriodic As Integer
End Structure

Module Module1
    <DllImport("DllTest.dll")> _
    Public Function StructFunc2(ByRef str_conf() As config_tag) As Integer
    End Function
End Module
************************************

Public Class Form1

    Private Sub Command1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Command1.Click
        Dim str_conf(4) As config_tag

        Call StructFunc2(str_conf)

    End Sub

End Class

******   エラーメッセージ  ************
マネージ デバッグ アシスタント 'PInvokeStackImbalance' では 'D:\VB_UseDll\WindowsApplication1\bin\Debug\WindowsApplication1.vshost.exe' に問題を検出しました。
追加情報: PInvoke 関数 'WindowsApplication1!WindowsApplication1.Module1::StructFunc2' がスタックを不安定にしています。PInvoke シグネチャがアンマネージ ターゲット シグネチャに一致していないことが原因として考えられます。呼び出し規約、および PInvoke シグネチャのパラメータがターゲットのアンマネージ シグネチャに一致していることを確認してください。
******************************************

構造体の引数をLongに変えたり、構造体メンバのマーシャリングをはずしたりしてみましたが、うまくいきませんでした。
構造体の先頭アドレスの渡し方がおかしいのかと思って、

宣言
Public Function StructFunc2(ByRef str_conf As config_tag) As Integer
呼び出し
Call StructFunc2(str_conf(0))
と、してみましたがだめでした。

上記のエラーメッセージは
Dll側で出しているメッセージボックス(・・・セットしました。)が出て、OKをクリックした後にでます。

よろしければ、ご教授お願い致します。


Hongliang  URL  2007-01-29 01:09:46  No: 135050

http://msdn2.microsoft.com/ja-jp/library/sd10k43k(VS.80).aspx
相互運用に手を出すなら熟読してください。
各種サンプルも載っています。もちろん、構造体配列を渡すようなサンプルも。


SQ  2007-01-29 02:18:17  No: 135051

>>HongLiang様
ご返答ありがとうございました。
どうやら、簡単にいくようなものではないようですね。
一応その辺は読んだつもりだったのですが、もう一度しっかりと熟読してみます。
現在も読みながら色々と変更を加えておりますがうまくいっておりません。
急ぎなのでゆっくりと読んでいる時間がないのですが・・・
ありがとうございました。


※返信する前に利用規約をご確認ください。




  


  このエントリーをはてなブックマークに追加