ページ 1 / 1
DLLでメモリエラー…
Posted: 2006年8月08日(火) 20:12
by Pon骨
はじめまして。ちょっと前からActiveBasicを使ってます。
さっそくAB5にてDLLを作ってみようと試したのですが、呼び出し時にメモリエラーになってしまいます。
コード: 全て選択
Dim iniFileName(255) As String
Function Export OpenFile(ByVal fID As Integer, ByVal sFileName As BytePtr) As Integer
If fID < 0 Or fID > 255 Then
OpenFile = 1
ElseIf iniFileName(fID) <> "" Then
OpenFile = 2
Else
iniFileName(fID) = MakeStr(sFileName)
OpenFile = 0
End If
End Function
このようなコードで、呼び出しはVB6から行いました。
コード: 全て選択
Private Declare Function OpenFile Lib "test.dll" (ByVal fID As Integer, ByVal sFileName As String) As Integer
Private Sub Form_Load()
Debug.Print OpenFile(0, App.Path & "\test.txt")
End Sub
MakeStrを無しにしてみたり、AB側のバグかなと思って4.24、4.23……4.20まで下げて試してみましたが全部同じメモリエラーが発生しました。
何がいけないのでしょうか、ご教授よろしくお願いします。
Posted: 2006年8月08日(火) 20:42
by konisi
VB6に関してはあまり詳しくはないのですが、VB側の第二引数がString型になっているので、それをByteptr型に直してみてください。
AB定義のString型とVB定義のString型に互換性がなければ、そこでエラーが起きている可能性があります。
・・・それと。
AB4xx系はAB413とAB420でシステムそのものが大きく変わっているので、AB424とAB423で変化を調べるより有効だと思います。
ただし、AB413では代入演算( += -=等)が使えなかった筈なので、移植する必要があると面倒ですが。
Posted: 2006年8月08日(火) 21:20
by Pon骨
>AB4xx系はAB413とAB420でシステムそのものが大きく変わっているので
AB4.13にて試しましたが同じエラーだったので、やはりコードのどこかに原因があるんだと思います。
>VB側の第二引数がString型になっているので、それをByteptr型に直してみてください
VBにBytePtr型は存在しません…
ABのBytePtrにVBからのStringを渡すことが出来ると認識していましたが、途中で仕様が変わったのでしょうか。
Posted: 2006年8月08日(火) 21:47
by konisi
BytePtr型は、基本的にByte型配列の先頭を指しています。
という事で、VBのString型をByte型の配列に代入して、(出来るかどうかはわからんが。)その配列の先頭をBytePtr型だと言えばいいかと思います。
ABでの方法
コード: 全て選択
Sub Form_Load()
Dim A$ As String,B As DWord
A$=MakeStr(App.path)+"\test.txt"
B=calloc(Len(A$)+1)
memcpy(B,A$,Len(A$))
#ifdef _DEBUG
MessageBox(0,Str$(OpenFile(0,B)),"debug",MB_OK)
#endif
free(B)
End Sub
Posted: 2006年8月08日(火) 22:39
by イグトランス
いいえ,VBのDeclareでString型を値渡し(ByVal)にすると,呼出時にその引数はANSI文字列へ変換されます。
ようするにABのBytePtrで受け取って全く問題ないはずです。
うまくいく例 [ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]たとえば次のコードなら問題なく動きます。
コード: 全て選択
Sub Export MyMsgBox(ByVal msg As BytePtr)
MessageBox(0, msg, "MyMsgBox", MB_OK)
End Sub
VBからはたとえば次のように呼び出します。
コード: 全て選択
Private Declare Sub MyMsgBox Lib "testdll" (ByVal msg As String)
Sub Test()
MyMsgBox ("Hello form Excel VBA!")
End Sub
なお私はVBを持っておらず,VBAで代用しています。(Excel 2003 VBA:VBのバージョンは6.0相当です)
そのVBAでもやはりPon骨さんのコードで落ちることは確認しました。
これからしばらく原因を探ってみたいと思います。
Posted: 2006年8月08日(火) 23:10
by イグトランス
AB5のDLLデバッグを利用したところ,iniFileNameが初期化されていないことが原因だとわかりました。
そこで,次の関数を追加し,
コード: 全て選択
Sub InitializeIniFileName()
Dim i As SIZE_T
For i = 0 To 255 'Len (iniFileName)
iniFileName(i) = ""
Next
End Sub
DllMainがDLL_PROCESS_ATTACHで呼び出されたときにInitializeIniFileName()を呼んでやるようにしたところ,
コード: 全て選択
Function Export DllMain(hinstDLL As HINSTANCE, fdwReason As DWord, pvReserved As VoidPtr) As BOOL
'DLLエントリポイント
Select Case fdwReason
Case DLL_PROCESS_ATTACH
'DLLがプロセス空間にロードされた時に実行されます。
_System_StartupProgram()
InitializeIniFileName()
DllMain = TRUE
End Select
End Function
AB5では正常に実行できるようになりました。
AB4では試していませんが,おそらく同様になると思います。
これはABのバグでしょう。それに対する回避策だと思ってください。
Posted: 2006年8月09日(水) 12:20
by Pon骨
動くようになりました。ありがとうございます。