Marshal

解決


n  2009-07-22 05:07:46  No: 146095

最近VB2008を始めました。
それまではVB6を使用してきました。

VB6側で

Type TThLog 
    Qso(3927) As Byte
End Type

Declare Function Vdbf_rcount Lib "Thdll2Vb.dll" (d As TThLog) As Long

これをVB2008側での一部のコードですが下記のようにしています。

Marshal  関係が分からずにエラーが出ていますが記述のアドバイスをいただけたらと思います。
Web検索などもしていますが難解で苦労しています。

    Structure TThLog
        <VBFixedArray(3927)> Dim Qso() As Byte
        Public Sub Initialize()
            ReDim Qso(3927)
        End Sub
    End Structure

    <DllImport("Thdll2Vb.dll")> _
    Private Shared Function Vdbf_rcount(<MarshalAs(UnmanagedType.LPTStr)> ByRef d As TThLog) As Integer
    End Function

        recno = Vdbf_rcount(log)


魔界の仮面弁士  2009-07-22 06:20:24  No: 146096

> VB6側で
> Type TThLog 
> Declare Function Vdbf_rcount Lib "Thdll2Vb.dll" (d As TThLog) As Long
引数は構造体の参照渡し、戻り値は 32bit 整数型、ですね。

> これをVB2008側での一部のコードですが下記のようにしています。
構造体に拘らないのであれば、
  Private Declare Function Vdbf_rcount Lib "Thdll2Vb" (ByRef qso As Byte) As Integer
にして、
  Dim log(3927) As Byte
  recno = Vdbf_rcount(log(0))
でいけるかも。

構造体で実装するなら、
  <StructLayout(LayoutKind.Seqential, Pack:=1)> Structure TThLog
    <MarshalAs(UnmanagedType.ByValArray, SizeConst:=3928)>Public QSo() As Byte
  End Sub
  Private Declare Function Vdbf_rcount Lib "Thdll2Vb" (ByRef qso As TThLog) As Integer
にして、
  Dim d As TThLog
  ReDim d.Qso(3927)
  recno = Vdbf_rcount(d)
とか。

# どちらも未確認。


n  2009-07-22 16:23:52  No: 146097

魔界の仮面弁士さん、ありがとうございます。

下記のようにして見ましたがファイルオープン時に
sdの返値が5になり失敗しているようです。  ゼロで成功。
        sd = Vdbf_open("C:\HAMLOG\Hamlog.hdb", d)

お気づきの箇所があればご指摘いただければ幸いです。

Imports System
Imports System.Text
Imports System.Windows.Forms
Imports System.Runtime.InteropServices

Public Class Form1

<StructLayout(LayoutKind.Sequential, Pack:=1)> Structure TThLog
        <MarshalAs(UnmanagedType.ByValArray, SizeConst:=3928)> Public QSo() As Byte
    End Structure
    Private Declare Function Vdbf_rcount Lib "Thdll2Vb.dll" (ByRef qso As TThLog) As Integer

<DllImport("Thdll2Vb.dll")> _
    Private Shared Function Vdbf_open(ByRef s As String, ByRef d As TThLog) As Integer
    End Function

    <DllImport("Thdll2Vb.dll")> _
    Private Shared Sub Vdbf_close(ByRef d As TThLog)
    End Sub

    Public Th As TDBFh
    Dim d As TThLog

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim sd As Integer
        Dim recno As Integer

        ReDim d.QSo(3927)

        sd = Vdbf_open("C:\HAMLOG\Hamlog.hdb", d)
        recno = Vdbf_rcount(d)
        Vdbf_close(d)
        Label2.Text = recno

    End Sub

End Class


魔界の仮面弁士  2009-07-22 18:16:03  No: 146098

Declare 構文と DllImport 構文が混じっているのが気になりますが、それはさておき。

> <DllImport("Thdll2Vb.dll")> _
> Private Shared Function Vdbf_open(ByRef s As String, ByRef d As TThLog) As Integer
> End Function

この部分があやしいです。この部分、本当に正しい宣言になっていますか?
String 型を DLL に ByRef で渡すのは、かなり特殊な状況に限られますよ。

Thdll2Vb.dll というのは、Windows や VB に標準で用意された物ではありませんし、
質問文には、VB2008 との比較対象となる VB6 当時のコードが無いので、
答えにくいのですが、DLL 名で検索してみると、下記の Th505API.lzh がヒットしました。
http://hamlog.no.coocan.jp/mou/

今回問題にしているのが、この DLL の事であるのかどうかは分かりませんが、
これを見ると、Vdbf_open というのは、

> int  WINAPI __export Vdbf_open(const char *fname, TThLog *th)
であり、かつ、VB6 から利用する場合には
> Declare Function Vdbf_open Lib "Thdll2Vb.dll" (ByVal s As String, d As TThLog) As Long
であると記載があります。

という事は、VB.NET からの利用は

Private Declare Function Vdbf_open Lib "Thdll2Vb" (ByVal s As String, ByRef d As TThLog) As Integer

もしくは、

Private Declare Ansi Function Vdbf_open Lib "Thdll2Vb" (ByVal s As String, ByRef d As TThLog) As Integer

になるかと思います。(未確認)


n  2009-07-22 18:35:00  No: 146099

魔界の仮面弁士 さん、ありがとうございました。

>今回問題にしているのが、この DLL の事であるのかどうかは分かりませんが、

はい、そのDLLです。
ご指摘の件などを踏まえて修正したところ  ファイルオープン、
レコード件数の取得も出来るようになりました。


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

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






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