長年VB6のプログラマをやっていた技術者がVB.NETでプログラムを作る時によく悩むのが
APIの宣言方法と引数の渡し方だと思います。特にVB6でAny、String、構造体を使っていた時に
VB.NETではどうするのか、、、長時間、検索エンジンに頼る事になると思います。
(VB.NETでAPIなんか使うな!! とか言わないの・・・)
VB6とVB.NETのDeclare(宣言)方法の違いのポイントは以下のような感じです。
(1)VB6のDeclareはVB.NETのDeclareに対応し同じなのです。
このサンプルではDeclareを使用していますが、<DllImport("mydll.dll")>を使用した方が
良いかもしれません。
(2)VB6のLongは4バイトなのでVB.NETのIntegerは4バイト(Longは8バイト)に対応します。
(3)VB6の"String * 10"のような変数の宣言はVB.NETの"New String("", 10)"に対応します。
ただし、構造体のメンバ変数の場合は(3)参照。
(4)構造体のメンバ変数が配列の場合の対応は以下のようになります。(サンプル有り)
・文字列の場合
(VB6 の場合)s2 As String * 7
(VB.NETの場合)<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=7)> Dim s2 As String
・配列の場合
(VB6 の場合)s4(1) As Long
(VB.NETの場合)<MarshalAs(UnmanagedType.ByValArray, SizeConst:=2)> Dim s4 As Integer()
(5)VB.NETにはAnyのような曖昧な宣言は出来ないので、最適な型に置き換えます。
(6)VB6のVariantはVB.NETのObjectに対応します。
サンプルソースを見た方が速いと思いますので、
VB6でのDeclare(宣言)方法とVB.NETでのDeclare(宣言)方法を比較したサンプルソースを以下に載せます。
このVB.NETのサンプルをC#.NETに移植したものがあります。
移植後のサンプルはVB6とC#.NETのAPI宣言(Declare)の違いを比較したサンプルです。
VB6とVB.NETとC#.NETのAPI宣言の比較が出来ます。
ちなみに、今回使用したAPIはVC++で作ったサンプルで、第一引数を第二引数にコピーする仕様です。
戻り値は第一引数のサイズを返します。VC++でDLLを作成するサンプルはこちらです。
VCからもVBからも呼び出せるDLLのサンプル(VC6)
<比較結果詳細>
1.VC++で作ったAPIのサンプルソース
typedef struct {
char s1;
char s2[7];
int s3;
int s4[2];
} MYSTRUCT;
__declspec(dllexport) int __stdcall MyCopyChar(char v1, char *v2){
*v2 = v1;
return sizeof(v1);
}
__declspec(dllexport) int __stdcall MyCopyString(char *v1, char *v2){
strcpy(v2, v1);
return strlen(v1);
}
__declspec(dllexport) int __stdcall MyCopyInteger(int v1, char *v2){
*v2 = v1;
return sizeof(v1);
}
__declspec(dllexport) int __stdcall MyCopyStruct(MYSTRUCT *v1, MYSTRUCT *v2){
v2->s1 = v1->s1;
memcpy(v2->s2, v1->s2, sizeof(v1->s2));
v2->s3 = v1->s3;
memcpy(v2->s4, v1->s4, sizeof(v1->s4));
return sizeof(*v1);
}
2.VB6からVC++のAPIを呼ぶサンプルソース
Private Type MYSTRUCT
s1 As Byte
s2 As String * 7
s3 As Long
s4(1) As Long
End Type
Private Declare Function MyCopyChar Lib "mydll.dll" _
(ByVal v1 As Byte, ByRef v2 As Byte) As Long
Private Declare Function MyCopyString Lib "mydll.dll" _
(ByVal v1 As String, ByVal v2 As String) As Long
Private Declare Function MyCopyInteger Lib "mydll.dll" _
(ByVal v1 As Long, ByRef v2 As Long) As Long
Private Declare Function MyCopyStruct Lib "mydll.dll" _
(ByRef v1 As MYSTRUCT, ByRef v2 As MYSTRUCT) As Long
Private Sub Command1_Click()
Dim rtn As Long
' APIの引数としてByteの値とByteの参照(アドレス)を渡す例
Dim v1_b As Byte
Dim v2_b As Byte
v1_b = 65
rtn = MyCopyChar(v1_b, v2_b)
Debug.Print ("------MyCopyChar------")
Debug.Print "v1_b=" & v1_b & ":" & "v2_b=" & v2_b
Debug.Print "rtn=" & rtn
' APIの引数としてStringの値とStringの参照(アドレス)を渡す例
Dim v1_s As String
Dim v2_s As String * 10
v1_s = "abcdefg"
rtn = MyCopyString(v1_s, v2_s)
Debug.Print ("------MyCopyString------")
Debug.Print "v1_s=" & v1_s & ":" & "v2_s=" & v2_s
Debug.Print "rtn=" & rtn
' APIの引数としてLongの値とLongの参照(アドレス)を渡す例
Dim v1_l As Long
Dim v2_l As Long
v1_l = 65
rtn = MyCopyInteger(v1_l, v2_l)
Debug.Print ("------MyCopyInteger------")
Debug.Print "v1_l=" & v1_l & ":" & "v2_l=" & v2_l
Debug.Print "rtn=" & rtn
' APIの引数として構造体(配列メンバ有り)の参照(アドレス)を渡す例
Dim v1_t As MYSTRUCT
Dim v2_t As MYSTRUCT
v1_t.s1 = 65
v1_t.s2 = "abcdefg123"
v1_t.s3 = 66
v1_t.s4(0) = 67
v1_t.s4(1) = 68
rtn = MyCopyStruct(v1_t, v2_t)
Debug.Print ("------MyCopyStruct------")
Debug.Print "v1_t.s1=" & v1_t.s1 & ":" & "v2_t.s1=" & v2_t.s1
Debug.Print "v1_t.s2=" & v1_t.s2 & ":" & "v2_t.s2=" & v2_t.s2
Debug.Print "v1_t.s3=" & v1_t.s3 & ":" & "v2_t.s3=" & v2_t.s3
Debug.Print "v1_t.s4(0)=" & v1_t.s4(0) & ":" & "v2_t.s4(0)=" & v2_t.s4(0)
Debug.Print "v1_t.s4(1)=" & v1_t.s4(1) & ":" & "v2_t.s4(1)=" & v2_t.s4(1)
Debug.Print "rtn=" & rtn
End Sub
===実行結果========================================
------MyCopyChar------
v1_b=65:v2_b=65
rtn=1
------MyCopyString------
v1_s=abcdefg:v2_s=abcdefg
rtn=7
------MyCopyInteger------
v1_l=65:v2_l=65
rtn=4
------MyCopyStruct------
v1_t.s1=65:v2_t.s1=65
v1_t.s2=abcdefg:v2_t.s2=abcdefg
v1_t.s3=66:v2_t.s3=66
v1_t.s4(0)=67:v2_t.s4(0)=67
v1_t.s4(1)=68:v2_t.s4(1)=68
rtn=20
3.VB.NET(2005)からVC++のAPIを呼ぶサンプルソース
Imports System.Runtime.InteropServices
Public Class Form1
Private Structure MYSTRUCT1
Dim s1 As Byte
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=7)> Dim s2 As String
Dim s3 As Integer
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=2)> Dim s4 As Integer()
End Structure
Private Structure MYSTRUCT2
Dim s1 As Byte
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=7)> Dim s2 As Byte()
Dim s3 As Integer
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=2)> Dim s4 As Integer()
End Structure
Private Structure MYSTRUCT3
Dim s1 As Byte
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=7)> Dim s2 As Byte()
Dim s3 As Integer
<MarshalAs(UnmanagedType.ByValArray, SizeConst:=2)> Dim s4 As Integer()
Sub New(ByVal dummy As Integer)
ReDim s2(6)
ReDim s4(1)
End Sub
End Structure
Private Declare Function MyCopyChar Lib "mydll.dll" _
(ByVal v1 As Byte, ByRef v2 As Byte) As Integer
Private Declare Function MyCopyString Lib "mydll.dll" _
(ByVal v1 As String, ByVal v2 As String) As Integer
Private Declare Function MyCopyString Lib "mydll.dll" _
(ByVal v1 As String, ByVal v2 As Byte()) As Integer
Private Declare Function MyCopyInteger Lib "mydll.dll" _
(ByVal v1 As Integer, ByRef v2 As Integer) As Integer
Private Declare Function MyCopyStruct Lib "mydll.dll" _
(ByRef v1 As MYSTRUCT1, ByRef v2 As MYSTRUCT1) As Integer
Private Declare Function MyCopyStruct Lib "mydll.dll" _
(ByRef v1 As MYSTRUCT2, ByRef v2 As MYSTRUCT2) As Integer
Private Declare Function MyCopyStruct Lib "mydll.dll" _
(ByRef v1 As MYSTRUCT3, ByRef v2 As MYSTRUCT3) As Integer
Private Sub Button1_Click( _
ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles Button1.Click
Dim rtn As Integer
' APIの引数としてByteの値とByteの参照(アドレス)を渡す例
Dim v1_b As Byte
Dim v2_b As Byte
v1_b = 65
rtn = MyCopyChar(v1_b, v2_b)
Debug.Print("------MyCopyChar------")
Debug.Print("v1_b=" & v1_b & ":" & "v2_b=" & v2_b)
Debug.Print("rtn=" & rtn)
' APIの引数としてStringの値とStringの参照(アドレス)を渡す例1
Dim v1_s1 As String
Dim v2_s1 As String = New String("", 10)
v1_s1 = "abcdefg"
rtn = MyCopyString(v1_s1, v2_s1)
Dim v2_s1_o As String = v2_s1
Dim l1 As Integer = v2_s1_o.IndexOf(Chr(0))
If l1 >= 0 Then v2_s1_o = v2_s1_o.Substring(0, l1)
Debug.Print("------MyCopyString1------")
Debug.Print("v1_s1=" & v1_s1 & ":" & "v2_s1=" & v2_s1_o)
Debug.Print("rtn=" & rtn)
' APIの引数としてStringの値とStringの参照(アドレス)を渡す例2
Dim v1_s2 As String
Dim v2_s2 As Byte() = New Byte(9) {}
v1_s2 = "abcdefg"
rtn = MyCopyString(v1_s2, v2_s2)
Dim v2_s2_o As String = _
System.Text.Encoding.GetEncoding("SHIFT-JIS").GetString(v2_s2)
Dim l2 As Integer = v2_s2_o.IndexOf(Chr(0))
If l2 >= 0 Then v2_s2_o = v2_s2_o.Substring(0, l2)
Debug.Print("------MyCopyString2------")
Debug.Print("v1_s2=" & v1_s1 & ":" & "v2_s2=" & v2_s2_o)
Debug.Print("rtn=" & rtn)
' APIの引数としてIntegerの値とIntegerの参照(アドレス)を渡す例
Dim v1_l As Integer
Dim v2_l As Integer
v1_l = 65
rtn = MyCopyInteger(v1_l, v2_l)
Debug.Print("------MyCopyInteger------")
Debug.Print("v1_l=" & v1_l & ":" & "v2_l=" & v2_l)
Debug.Print("rtn=" & rtn)
' APIの引数として構造体(配列メンバ有り)の参照(アドレス)を渡す例1
Dim v1_t1 As MYSTRUCT1 = New MYSTRUCT1
Dim v2_t1 As MYSTRUCT1 = New MYSTRUCT1
v1_t1.s1 = 65
v1_t1.s2 = "abcdefg123"
v1_t1.s3 = 66
v1_t1.s4 = New Integer(1) {67, 68}
rtn = MyCopyStruct(v1_t1, v2_t1)
Debug.Print("------MyCopyStruct1------")
Debug.Print("v1_t1.s1=" & v1_t1.s1 & ":" & "v2_t1.s1=" & v2_t1.s1)
Debug.Print("v1_t1.s2=" & v1_t1.s2 & ":" & "v2_t1.s2=" & v2_t1.s2)
Debug.Print("v1_t1.s3=" & v1_t1.s3 & ":" & "v2_t1.s3=" & v2_t1.s3)
Debug.Print("v1_t1.s4(0)=" & v1_t1.s4(0) & ":" & "v2_t1.s4(0)=" & v2_t1.s4(0))
Debug.Print("v1_t1.s4(1)=" & v1_t1.s4(1) & ":" & "v2_t1.s4(1)=" & v2_t1.s4(1))
Debug.Print("rtn=" & rtn)
' APIの引数として構造体(配列メンバ有り)の参照(アドレス)を渡す例2
Dim v1_t2 As MYSTRUCT2 = New MYSTRUCT2
Dim v2_t2 As MYSTRUCT2 = New MYSTRUCT2
v1_t2.s1 = 65
v1_t2.s2 = System.Text.Encoding.GetEncoding("SHIFT-JIS").GetBytes("abcdefg123")
v1_t2.s3 = 66
v1_t2.s4 = New Integer(1) {67, 68}
rtn = MyCopyStruct(v1_t2, v2_t2)
Debug.Print("------MyCopyStruct2------")
Debug.Print("v1_t2.s1=" & v1_t2.s1 & ":" & "v2_t2.s1=" & v2_t2.s1)
Debug.Print("v1_t2.s2=" & _
System.Text.Encoding.GetEncoding("SHIFT-JIS").GetString(v1_t2.s2) & _
":" & "v2_t.s2=" & _
System.Text.Encoding.GetEncoding("SHIFT-JIS").GetString(v2_t2.s2))
Debug.Print("v1_t2.s3=" & v1_t2.s3 & ":" & "v2_t2.s3=" & v2_t2.s3)
Debug.Print("v1_t2.s4(0)=" & v1_t2.s4(0) & ":" & "v2_t.s4(0)=" & v2_t2.s4(0))
Debug.Print("v1_t2.s4(1)=" & v1_t2.s4(1) & ":" & "v2_t.s4(1)=" & v2_t2.s4(1))
Debug.Print("rtn=" & rtn)
' APIの引数として構造体(配列メンバ有り)の参照(アドレス)を渡す例3
Dim v1_t3 As MYSTRUCT3 = New MYSTRUCT3(0)
Dim v2_t3 As MYSTRUCT3 = New MYSTRUCT3(0)
v1_t3.s1 = 65
v1_t3.s2(0) = Asc("a")
v1_t3.s2(1) = Asc("b")
v1_t3.s2(2) = Asc("c")
v1_t3.s2(3) = Asc("d")
v1_t3.s2(4) = Asc("e")
v1_t3.s2(5) = Asc("f")
v1_t3.s2(6) = Asc("g")
v1_t3.s3 = 66
v1_t3.s4(0) = 67
v1_t3.s4(1) = 68
rtn = MyCopyStruct(v1_t3, v2_t3)
Debug.Print("------MyCopyStruct3------")
Debug.Print("v1_t3.s1=" & v1_t3.s1 & ":" & "v2_t3.s1=" & v2_t3.s1)
Debug.Print("v1_t3.s2=" & _
System.Text.Encoding.GetEncoding("SHIFT-JIS").GetString(v1_t3.s2) & _
":" & "v2_t3.s2=" & _
System.Text.Encoding.GetEncoding("SHIFT-JIS").GetString(v2_t3.s2))
Debug.Print("v1_t3.s3=" & v1_t3.s3 & ":" & "v2_t3.s3=" & v2_t3.s3)
Debug.Print("v1_t3.s4(0)=" & v1_t3.s4(0) & ":" & "v2_t3.s4(0)=" & v2_t3.s4(0))
Debug.Print("v1_t3.s4(1)=" & v1_t3.s4(1) & ":" & "v2_t3.s4(1)=" & v2_t3.s4(1))
Debug.Print("rtn=" & rtn)
End Sub
End Class
===実行結果========================================
------MyCopyChar------
v1_b=65:v2_b=65
rtn=1
------MyCopyString1------
v1_s1=abcdefg:v2_s1=abcdefg
rtn=7
------MyCopyString2------
v1_s2=abcdefg:v2_s2=abcdefg
rtn=7
------MyCopyInteger------
v1_l=65:v2_l=65
rtn=4
------MyCopyStruct1------
v1_t1.s1=65:v2_t1.s1=65
v1_t1.s2=abcdefg:v2_t1.s2=abcdefg
v1_t1.s3=66:v2_t1.s3=66
v1_t1.s4(0)=67:v2_t1.s4(0)=67
v1_t1.s4(1)=68:v2_t1.s4(1)=68
rtn=20
------MyCopyStruct2------
v1_t2.s1=65:v2_t2.s1=65
v1_t2.s2=abcdefg:v2_t.s2=abcdefg
v1_t2.s3=66:v2_t2.s3=66
v1_t2.s4(0)=67:v2_t.s4(0)=67
v1_t2.s4(1)=68:v2_t.s4(1)=68
rtn=20
------MyCopyStruct3------
v1_t3.s1=65:v2_t3.s1=65
v1_t3.s2=abcdefg:v2_t3.s2=abcdefg
v1_t3.s3=66:v2_t3.s3=66
v1_t3.s4(0)=67:v2_t3.s4(0)=67
v1_t3.s4(1)=68:v2_t3.s4(1)=68
rtn=20
|
|