tagCANDY CGI VBレスキュー(花ちゃん)の Visual Basic 6.0用 掲示板 [ツリー表示へ]   [Home]
一括表示(VB6.0)
タイトル異なる構造体の関数渡し
記事No14551
投稿日: 2010/03/16(Tue) 14:52
投稿者クン
■環境 VB6.0
種類の異なる構造体を引数として渡したいのですが、
下記の@が型不一致となってしまいます。
ネット、サンプル等、見てもヒントが見付かりません。
どうぞ、宜しくお願い致します。

<呼出側>
Public Type ENE_SHM_PWR_INFO
    failCount As Integer                    '連続計測失敗カウンタ
    refPower As Integer                     '消費電力量
End Type
Public Type ENE_SHM_REF_POWER
    makeTime As String * 14                 '最新計測年月日時分秒
    reserved As String * 2                  '予約
    powerInfo(1 To 16) As ENE_SHM_PWR_INFO  '要冷機電力情報
End Type
Dim wShm As ENE_SHM_REF_POWER
    wRet = Ene_VbCmnSmAccess(ENE_SHM_WRITE, ENE_SHM_MAP_REFPOWER, _
                             ENE_SHM_MTX_REFPOWER, @wShm, Len(wShm), Me)
<関数側>
Public Function Ene_VbCmnSmAccess(iAcs As Integer, iMap As String, _
                                  iMtx As String, ByRef iSmp As Variant, _
                                  iSms As Integer, iFrm As Form) As Integer

[ツリー表示へ]
タイトルRe: 異なる構造体の関数渡し
記事No14552
投稿日: 2010/03/16(Tue) 15:20
投稿者魔界の仮面弁士
> ■環境 VB6.0
> 種類の異なる構造体を引数として渡したいのですが、
> 下記の@が型不一致となってしまいます。

ユーザー定義型にこだわる必要が無いのであれば、そのデータ型を
クラスに変更してみてください。そうすれば、As Object 引数として渡せます。

それができないのであれば、諦めてそれぞれに別名のメソッドを用意してください。


なお、異なるユーザー定義型を同じ引数にて渡せる条件としては、
下記の 2 パターンいずれかに限られます。

(a) Declare 宣言でアクセス可能な外部公開されている関数に対し、As Any 引数として渡す場合。

(b) パブリック オブジェクト モジュールで宣言されたユーザー定義型を、As Variant 引数として渡す場合。

[ツリー表示へ]
タイトルRe^2: 異なる構造体の関数渡し
記事No14554
投稿日: 2010/03/16(Tue) 15:33
投稿者クン
魔界の仮面弁士さん、迅速な返信、ありがとうございます。

> ユーザー定義型にこだわる必要が無いのであれば、そのデータ型を
> クラスに変更してみてください。そうすれば、As Object 引数として渡せます。

クラスにする方法が分かりません。
異なる構造体3種は共有メモリです。
其のポインタとサイズでMoveMemory()したいのです。
単に、Cの void * として取り扱いたいだけなのですが…。

[ツリー表示へ]
タイトルRe^3: 異なる構造体の関数渡し
記事No14555
投稿日: 2010/03/16(Tue) 17:59
投稿者魔界の仮面弁士
ByRef iSmp As Variant を、
ByRef iSmp As ENE_SHM_REF_POWER に
変更したメソッドを用意するだけでは都合が悪いのでしょうか?

どうしても Variant 引数にしたいのであれば、先述のパターン(b)にするために、
そのユーザー定義型を ActiveX DLL のプロジェクトなどとして登録する必要があるかと。


> クラスにする方法が分かりません。
であれば、止めておいたほうが良いかと思います。


> 異なる構造体3種は共有メモリです。
ENE_SHM_PWR_INFO と ENE_SHM_REF_POWER の 2 種ではありませんでしたっけ?


> 其のポインタとサイズでMoveMemory()したいのです。
> 単に、Cの void * として取り扱いたいだけなのですが…。
API との受け渡しであれば、ByRef As Any 引数にすれば、任意のユーザー定義型を
ポインタとして渡せますが……VB 側のプロシージャではそうはいきません。

それぞれのユーザー定義型のサイズに互換性があれば、LSet で
一方の型に変換するという手もありますけれどね。


あるいは、それぞれのユーザー定義型を「Byte 配列に変換する関数」や
「Byte 配列を受け取り、それをユーザー定義型として返す関数」を
用意するというのは如何でしょう。
呼び出しの手間は増えますが、Byte 配列で交換するのであれば
RtlMoveMemory / MoveMemory への影響は無いと思います。

[ツリー表示へ]
タイトルRe^4: 異なる構造体の関数渡し
記事No14556
投稿日: 2010/03/16(Tue) 18:46
投稿者クン
> ByRef iSmp As Variant を、
> ByRef iSmp As ENE_SHM_REF_POWER に
> 変更したメソッドを用意するだけでは都合が悪いのでしょうか?

3種類の構造体を止め、ご指摘の通り、個々の関数に分割しました。

[呼出側]
    Dim wShm As ENE_SHM_REF_POWER
    wRet = Ene_WriteShmRefPower(wShm, Len(wShm), Me)

[関数側]
Private Function Ene_WriteShmRefPower(iSmp As ENE_SHM_REF_POWER, _
                                      iSms As Long, iFrm As Form) As Integer

    Dim wAtr As SECURITY_ATTRIBUTES
    Dim wRet As Integer
    Dim wHmx As Long
    Dim wHmp As Long
    Dim wShm As Long

    'ミューテックスの生成
    wHmx = CreateMutex(wAtr, 0, ENE_SHM_MTX_REFPOWER)
    If wHmx <> 0 Then
        '排他待ち
        If WaitForSingleObject(wHmx, -1) = WAIT_OBJECT_0 Then
            'マッピングファイルのオープン
            wHmp = OpenFileMapping(FILE_MAP_WRITE, 0, ENE_SHM_MAP_REFPOWER)
            If wHmp <> 0 Then
                'マップファイルのマッピング
                wShm = MapViewOfFile(wHmp, FILE_MAP_WRITE, 0, 0, 0)
                If wShm <> 0 Then
                    '共有メモリの書き込み
                    Call MoveMemory(wShm, iSmp, iSms)
                    wRet = ENE_RET_SUCCESS
                Else
                    Beep
                    MsgBox "マッピングファイルのマッピングに失敗しました。" _
                            & vbCrLf & "[" & ENE_SHM_MAP_REFPOWER & "]", _
                            vbCritical + vbOKOnly, iFrm.Caption
                    wRet = ENE_RET_MAP_PING_ERR
                End If
            Else
                Beep
                MsgBox "マッピングファイルのオープンに失敗しました。" _
                        & vbCrLf & "[" & ENE_SHM_MAP_REFPOWER & "]", _
                        vbCritical + vbOKOnly, iFrm.Caption
                wRet = ENE_RET_MAP_OPEN_ERR
            End If
        End If
    Else
        Beep
        MsgBox "ミューテックスの生成に失敗しました。" _
                & vbCrLf & "[" & ENE_SHM_MTX_REFPOWER & "]", _
                vbCritical + vbOKOnly, iFrm.Caption
        wRet = ENE_RET_MTX_CREATE_ERR
    End If
    'リソースの返却
    If wShm <> 0 Then
        Call UnmapViewOfFile(wShm)
    End If
    If wHmp <> 0 Then
        Call CloseHandle(wHmp)
    End If
    If wHmx <> 0 Then
        Call ReleaseMutex(wHmx)
        Call CloseHandle(wHmx)
    End If
    Ene_WriteShmRefPower = wRet
End Function

然しながら、MoveMemory()で落ちてしまいます。
もう完璧に嵌ってしまいました、ご教授の程、宜しくお願い致します。

[ツリー表示へ]
タイトルRe: 異なる構造体の関数渡し
記事No14557
投稿日: 2010/03/17(Wed) 08:44
投稿者K.J.K.
> 然しながら、MoveMemory()で落ちてしまいます。

MoveMemory がどう宣言されているのかにもよりますが、

>                     Call MoveMemory(wShm, iSmp, iSms)

wShmがポインタであるようなので、ByVal を付けるとか。例えば、
Call MoveMemory(ByVal wShm, iSmp, iSms)

# それらとは別に、WaitForSingleObjet での無限秒待ちはリスクが高いような。

[ツリー表示へ]