質問者
返却されたパラメータが一次元になる。

質問
-
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 IntegerTry
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);
すべての返信
-
配列の構造が、VBとは違うのではないでしょうか?
VCの配列は単に連続したメモリなだけですし。
参考:配列に対する既定のマーシャリング -
端的に言うと仕様です。
マーシャリングの際、C スタイルの配列は強制的に 1 次元配列とみなされてマーシャリングされます。詳しくは MSDN で 「配列に対する既定のマーシャリング」「さまざまな型の配列のマーシャリング」辺りの記事をご覧ください。
.NET 側では各次元の要素数の積だけの要素数を持った 1 次元配列を使用することになります。
それはそうと、Declare ステートメントで配列をパラメータに宣言するなら、
ByRef As 型
よりもByVal As 型()
の方が良いでしょう。.NET では配列の先頭からメモリ上正しく並んでいるという保証はありませんから(配列で宣言しておけばフレームワークがうまいことやってくれます)。// というか ByRef As 型 が使えることにびっくり。
-
蒼の洞窟さん、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