DOBON.NET DOBON.NETプログラミング掲示板過去ログ

DLL 型変換の件

環境/言語:[Vb.Net]
分類:[.NET]

DLL "Any”の扱いについて教えてください。
VB6.0→VB.NETに組み込みましたが、正常に動作しません。
LONG→INTEGER、
Any→Integerに変換しましたが同じです。
各変数の型をどのように変えればよろしいでしょうか。

[VB6.0]
Declare Function TmReceiveBin Lib "****.dll" Alias "TmReceive" (ByVal id As Long, ByRef buf As Any, ByVal blen As Long, ByRef rlen As Long) As Long

Function TmReceive(ByVal id As Long, ByRef buf As String, ByVal blen As Long, ByRef rlen As Long)
TmReceive = TmReceiveBin(id, ByVal buf, blen, rlen)
> 各変数の型をどのように変えればよろしいでしょうか。
対処方法としては、VB のヘルプにあるように、適切な型のオーバーロードで解決するか、
MarshalAs(UnmanagedType.AsAny) 属性を使うかですね。ただ、UnmanagedType.AsAny の
指定は、若干扱い難い面もありますので、オーバーロードで解決させた方が安全でしょう。


ただし、どのように書き換えるべきかは、DLL 側の仕様によります。

Any 宣言は、「状況によって渡すべき型が変わる場合」に使われるのですが、
そこにどのような型を渡すべきなのかは、DLL側の実装に依存するからです。


> Declare Function TmReceiveBin Lib "****.dll" Alias "TmReceive" _
> (ByVal id As Long, ByRef buf As Any, ByVal blen As Long, ByRef rlen As Long) As Long
> 
> Function TmReceive(ByVal id As Long, ByRef buf As String, ByVal blen As Long, ByRef rlen As Long)
>     TmReceive = TmReceiveBin(id, ByVal buf, blen, rlen)

DLL 側の仕様が分からないので、確かな事は言えませんが、TmReceiveBin を呼び出しているのが
上記の部分だけだとしたら、渡すべき型が一種類しかありませんので、オーバーロードも使わず、

  Declare Function TmReceiveBin Lib "****.dll" Alias "TmReceive" _
  (ByVal id As Integer, ByVal buf As String, ByVal blen As Integer, ByRef rlen As Integer) As Integer

だけで済むように思えます。
DLL 側の仕様によっては As StringBuilder の方がよいかもしれませんけれどね。
■No15375に返信(魔界の仮面弁士さんの記事)
> > 各変数の型をどのように変えればよろしいでしょうか。
> 対処方法としては、VB のヘルプにあるように、適切な型のオーバーロードで解決するか、
> MarshalAs(UnmanagedType.AsAny) 属性を使うかですね。ただ、UnmanagedType.AsAny の
> 指定は、若干扱い難い面もありますので、オーバーロードで解決させた方が安全でしょう。
>
>
> ただし、どのように書き換えるべきかは、DLL 側の仕様によります。
>
> Any 宣言は、「状況によって渡すべき型が変わる場合」に使われるのですが、
> そこにどのような型を渡すべきなのかは、DLL側の実装に依存するからです。
>
>
>>Declare Function TmReceiveBin Lib "****.dll" Alias "TmReceive" _
>>(ByVal id As Long, ByRef buf As Any, ByVal blen As Long, ByRef rlen As Long) As Long
>>
>>Function TmReceive(ByVal id As Long, ByRef buf As String, ByVal blen As Long, ByRef rlen As Long)
>> TmReceive = TmReceiveBin(id, ByVal buf, blen, rlen)
>
> DLL 側の仕様が分からないので、確かな事は言えませんが、TmReceiveBin を呼び出しているのが
> 上記の部分だけだとしたら、渡すべき型が一種類しかありませんので、オーバーロードも使わず、
>
> Declare Function TmReceiveBin Lib "****.dll" Alias "TmReceive" _
> (ByVal id As Integer, ByVal buf As String, ByVal blen As Integer, ByRef rlen As Integer) As Integer
>
> だけで済むように思えます。
> DLL 側の仕様によっては As StringBuilder の方がよいかもしれませんけれどね。



連絡ありがとうございました。
ご指示の内容で確認しました。
●ByRef Buf As Any → ByVal Buf As String          

結果: 通信データ 最初の1文字は、受信できます。
     パケットモニター ”4410” → Buf内容 "4"

●ByRef Buf As Any → ByRef Buf As String 
 ”インスタンスエラー”となります。

以上の結果です。
testerさん,こんにちは。

> ●ByRef Buf As Any → ByVal Buf As String          
>
> 結果: 通信データ 最初の1文字は、受信できます。
>      パケットモニター ”4410” → Buf内容 "4"

魔界の仮面弁士さんもおっしゃっているようにStringBuilderで試したら
どうでしょうか。

それでもだめならIntPtrで受け取って,
Marshal.PtrToStringAnsiなどのPtrToStringXXXXXメソッドで文字列を
取得するようにしたらどうでしょうか。
  • 題名: Re[3]: DLL 型変換の件
  • 著者: 魔界の仮面弁士
  • 日時: 2006/03/03 18:02:00
  • ID: 15400
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
> 以上の結果です。
もしかして回答ではなく、具体的な解答を求めてますか?
だとしたら、DLL 側の仕様を教えてもらわないとどうにもなりません。

Anyは元々、「何でもアリ」な型なので、どのように再定義すべきかは、
DLL 側の仕様がわからないと、推論でしか判断できないです。(^_^;)

# Windows の標準的な API ならまだしも、google にすらヒットしない API名で、
# DLL 名も明かされず、その上 API 仕様も不明となると、答えようが……。


> 結果: 通信データ 最初の1文字は、受信できます。
>      パケットモニター ”4410” → Buf内容 "4"
これも、先の API がどのような機能を持ったものなのかの説明も無しに、
いきなりパケットモニターがどうとか言われても、正直、何の事やら。(^_^;)


とりあえず、一文字目以降が切れている事なので、API 宣言を
Ansiモードにして試してみては如何でしょう。

それでも駄目なら……『TmReceive"Bin"』という別名をつけているようなので、
バイナリ操作のために、ByVal buf() As Byte を渡すようにしてみるとか。

それでも駄目なら、ByRef buf As IntPtr で宣言して、そのポインタを、
Marshal.ReadByteなどを使って読み書きするという最終手段で。


> ●ByRef Buf As Any → ByRef Buf As String 
>  ”インスタンスエラー”となります。
DLL 側の仕様にもよりますが、おそらく、これは無いと思いますよ。
ByRef String での宣言を必要するタイプの API は、さほど多くありませんし。
■No15398に返信(YASさんの記事)
> testerさん,こんにちは。
>
>>●ByRef Buf As Any → ByVal Buf As String          
>>
>>結果: 通信データ 最初の1文字は、受信できます。
>>     パケットモニター ”4410” → Buf内容 "4"
>
> 魔界の仮面弁士さんもおっしゃっているようにStringBuilderで試したら
> どうでしょうか。
>
> それでもだめならIntPtrで受け取って,
> Marshal.PtrToStringAnsiなどのPtrToStringXXXXXメソッドで文字列を
> 取得するようにしたらどうでしょうか。
>



連絡ありがとうがざいました。
”StringBuilder ”確認しましたが、 受信文字””で何もありません。

> それでもだめならIntPtrで受け取って,
> Marshal.PtrToStringAnsiなどのPtrToStringXXXXXメソッドで文字列を
> 取得するようにしたらどうでしょうか。
の提案ですが、できれば詳細をご教授ください。
>>それでもだめならIntPtrで受け取って,
>>Marshal.PtrToStringAnsiなどのPtrToStringXXXXXメソッドで文字列を
>>取得するようにしたらどうでしょうか。
> の提案ですが、できれば詳細をご教授ください。

DLL側でメモリをAllocするという前提です。

Declare Function TmReceiveBin Lib "****.dll" Alias "TmReceive" _
(ByVal id As Integer, ByVal buf As Intptr, ByVal blen As Integer, ByRef rlen As Integer) As Integer

Dim buf as IntPtr
TmReceive = TmReceiveBin(id, ByVal buf, blen, rlen)
Dim strBuf as String = Marshal.PtrToStringAnsi(buf)

でもこれだとbufのメモリの解放ができません。

DLL側の仕様がよくわからないので,なんとも言えません。
(bufのメモリは呼び出す側で用意するのですか?それともDLL側で確保されるの
ですか?)
>Declare Function TmReceiveBin Lib "****.dll" Alias "TmReceive" (ByVal id As Long, ByRef buf As Any, ByVal blen As Long, ByRef rlen As Long) As Long

>Function TmReceive(ByVal id As Long, ByRef buf As String, ByVal blen As Long, ByRef rlen As Long)
>TmReceive = TmReceiveBin(id, ByVal buf, blen, rlen)

DllのbBufの宣言をByt型にして、
ByRef buf As Any → ByRef buf As Byte

Dim sBuf as String

String型に変換して、
sBuf = Encoding.GetEncoding("Shift_JIS").GetString(buf)

TmReceive = TmReceiveBin(id, ByVal sBuf, blen, rlen)

では、だめでしょうか?

間違っていたらすいません。

DOBON.NET | プログラミング道 | プログラミング掲示板