2010/04/19(Mon) 11:08:21 編集(投稿者)
検証してみました。簡単な動作確認しかしてませんので、本当に問題ないかは十分な検証が必要です。
環境:
OS:WinXP SP2 (32bit)
・VBはVB9.0のコンパイラでコンパイル
・VC++はVC++2008でコンパイル
(VC++側は、明示的なアラインメントの調整の指定はしていません
(コンパイルのオプションや#pragma packの指定))
※StructLayoutのPackの指定を1,2,4,8で試してみましたが、
以下のコードの範囲では、4と8なら一応うまく行くようです。
(VC++側のデフォルトのアラインメント調整のバイト数を確認する必要がありますね。
32bit/64bit環境のどちらで動くのか、というのも重要そう)
--
' VB側の実験コード コンソールアプリとしてvbc.exeでコンパイル
Imports System
Imports System.Runtime.InteropServices
Module Program
<DllImport("DllTest.dll", CharSet:=CharSet.Ansi, ExactSpelling:=true)> _
Public Sub DbRGetMenuMsg(ByRef buf As ProgMenu)
End Sub
Sub Main()
Dim pm As ProgMenu = new ProgMenu()
pm.s1 = new ptMenu(63 * 9-1){}
pm.s1(0).iEnable = 12
pm.s1(0).iName = "a123456789b"
pm.s1(0).iBackColor = 345
pm.s1(0).iMenuFlag = 6789
pm.s1(63 * 9 - 1).iEnable = 21
pm.s1(63 * 9 - 1).iName = "b123456789a"
pm.s1(63 * 9 - 1).iBackColor = 543
pm.s1(63 * 9 - 1).iMenuFlag = 9876
DbRGetMenuMsg(pm)
Console.ReadKey()
End Sub
End Module
<StructLayout(LayoutKind.Sequential, Pack:=4, CharSet:=CharSet.Ansi)> _
Structure ptMenu
Public iEnable As Short
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=12)> public iName As String
Public iBackColor As Integer
Public iMenuFlag As Short
End Structure
<StructLayout(LayoutKind.Sequential, Pack:=4)> _
Structure ProgMenu
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=63 * 9)> Public s1 As ptMenu()
End Structure
--
/* VC++側のコード DLL用のプロジェクトを新規作成して以下のコードを記述 */
/* DEFファイルを定義してリンカーオプションで指定 */
// DllTest.cpp : DLL アプリケーション用にエクスポートされる関数を定義します。
#include "stdafx.h"
#include <stdio.h>
#define TMENUMAX 63 * 9
typedef struct {
short iEnable;
char Name[12];
long iBackColor;
short iMenuFlag;
} stMenu;
typedef struct {
stMenu sdProgMenu[TMENUMAX];
} vbProgMenu;
extern "C" void WINAPI DbRGetMenuMsg( vbProgMenu *buf )
{
/* 動作確認のため構造体の中身を確認 */
/* 量が多いので最初と最後の要素だけ */
int i = 0;
for (i = 0; i < TMENUMAX; i++)
{
if (i ==0 || i == TMENUMAX-1)
{
printf("i=%d\n", i);
printf("iEnable=%d\n", buf->sdProgMenu[i].iEnable);
printf("Name[12]=%s\n", buf->sdProgMenu[i].Name);
printf("iBackColor=%d\n", buf->sdProgMenu[i].iBackColor);
printf("iMenuFlag=%d\n", buf->sdProgMenu[i].iMenuFlag);
}
}
}
--
<修正>
環境まわりの説明を補足
</修正>