C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[6]: VB.net⇒VC++6.0のVoid型に構造体配列参照渡


(過去ログ 127 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■75559 / inTopicNo.1)  VB.net⇒VC++6.0のVoid型に構造体配列参照渡
  
□投稿者/ とら (15回)-(2015/04/07(Tue) 18:40:12)

分類:[VB.NET/VB2005 以降] 

2015/04/07(Tue) 19:07:10 編集(投稿者)

以前こちらで質問させて頂き無事解決に至りましたが、また別途問題が発生し自力での解決に至らないため再度お世話になります。・

前回と同じ状況ですが、VB6.0で作成した実行ファイルからVC++6.0で作成したDLLに値を参照渡ししているものがあり、
このたびVB.net2008にアップグレードする事になりました。


前回はSAFEARRAYに対しての構造体配列渡しでしたが、今回は受け先がVoid型となります。

そして複数の個所から異なる構造体を渡していて、VC側で処理を分けているようです。

(VB6.0ではDeclareのところでAny型が指定してありましたが、型を明示的にして複数用意しました)


受け先がvoid型の場合はそもそも無理だったりするのでしょうか。

SafeArrayの時と同じようなCOM公開や、下記を参考にしDeclare 及び 構造体宣言部分にマーシャリングを指定してみたりと
あれこれやってみたのですが、SafeArrayと同じ方法だと「ライブラリの形式が古いか、または種類が無効です」といったエラーが発生し、
下記を参考にしたマーシャリングの設定だと参照先が「block type is valid」といったポインタ絡みのエラー?的なものを出したりと
独力ではどうにもならない状態です。

https://msdn.microsoft.com/ja-jp/library/hk9wyw21(v=vs.110).aspx
https://msdn.microsoft.com/ja-jp/library/eadtsekz(v=vs.110).aspx


根本的にマーシャリングについて理解が及ばずお恥ずかしい限りなのですが、何卒宜しくお願い致します。


ソースは以下のようになります。


## VC++6.0 ###########

Test1_API int __stdcall Test1(void *Data1)


## VB6.0 #############

-- 宣言部 ----

Declare Function Test1 Lib "Test.DLL" (ByRef oType() As Any) As Long

Public Type Type1
Str1 As String
Str2 As String
Str3 As String
End Type

Public Type Type2
Str4 As String
Str5 As String
Str6 As String
End Type

Public oType1(0 To 9) As Type1
Public oType2(0 To 9) As Type2


-- 処理 ----

Dim iRet As Long
iRet = Test1(oType1())
iRet = Test1(oType2())


## VB2008 #############

-- 宣言部 ----

Declare Function Test1 Lib "Test.DLL" (ByVal oStructure() As Structure1) As Integer
Declare Function Test1 Lib "Test.DLL" (ByVal oStructure() As Structure2) As Integer


Public Structure Structure1
Dim Str1 As String
Dim Str2 As String
Dim Str3 As String
End Structure

Public Structure Structure2
Dim Str4 As String
Dim Str5 As String
Dim Str6 As String
End Structure

Public oStructure1(9) As Structure1
Public oStructure2(9) As Structure2


-- 処理 ----

Dim iRet As Integer = -1
iRet = Test1(oStructure1)
iRet = Test1(oStructure2)

引用返信 編集キー/
■75561 / inTopicNo.2)  Re[1]: VB.net⇒VC++6.0のVoid型に構造体配列参照渡
□投稿者/ 魔界の仮面弁士 (279回)-(2015/04/08(Wed) 00:13:27)
2015/04/08(Wed) 00:18:46 編集(投稿者)

No75559 (とら さん) に返信
> そして複数の個所から異なる構造体を渡していて、VC側で処理を分けているようです。
> (VB6.0ではDeclareのところでAny型が指定してありましたが、型を明示的にして複数用意しました)
まぁ、オーバーロードで対応するのが無難でしょうね。


> 受け先がvoid型の場合はそもそも無理だったりするのでしょうか。
型が不定でオーバーロードできないケースだと、Any の代用として
Object なり IntPtr なりでやりとりすることになるかも。


ただいずれにせよ、構造体側のマーシャリング指定は必要だと思います。
「文字列型」や「他の構造体」を含んでいる構図体の場合は特に。
(期待される文字列が、BSTR なのか LPCTSTR なのかなど)
https://msdn.microsoft.com/ja-jp/library/s9ts558h.aspx
引用返信 編集キー/
■75590 / inTopicNo.3)  VB.net⇒VC++6.0のVoid型に構造体配列参照渡
□投稿者/ とら (16回)-(2015/04/10(Fri) 13:14:30)
2015/04/10(Fri) 13:23:13 編集(投稿者)

No75561 (魔界の仮面弁士 さん) に返信

>ただいずれにせよ、構造体側のマーシャリング指定は必要だと思います。
>「文字列型」や「他の構造体」を含んでいる構図体の場合は特に。
>(期待される文字列が、BSTR なのか LPCTSTR なのかなど)

BSTRとして指定しマーシャリングを追加して呼び出しを行うよう下記のように変更して実行してみたのですが、依然として配列の受け渡しに失敗している様子。

< StructLayout( LayoutKind.Sequential, CharSet:=CharSet.Ansi )>
Public Structure Structure1
<MarshalAs(UnmanagedType.BStr)> Dim Str1 As String
<MarshalAs(UnmanagedType.BStr)> Dim Str2 As String
<MarshalAs(UnmanagedType.BStr)> Dim Str3 As String
End Structure

Declare Function Test1 Lib "Test.DLL" (<[In], [Out]> ByVal oStructure() As Structure1) As Integer


受け取り側のvoid型のところが、受け取った後にSafeArrayにキャストして別の関数に渡していたので、Void型をSafeArrayに変更し以前と同じ対応としてCom公開をしてみようとしたところ、AssemblyInfo.vbに追加する際にComVisivleおよびGuidを複数回適用することはできないというエラーが表示され設定できませんでした。

以前のご説明では複数の構造体がある場合はAssemblyInfo.vbにも複数追加するという旨が記載されていたと思いますが、この場合どのように定義すればよろしいのでしょうか。

AssemblyInfo.vbは前回築城したもののみとし、今回の構造体にのみ新規作成したGuidを設定してDeclareにもマーシャリングを追加致しましたが、「ライブラリの形式が古いか、または種類が無効です」というエラーが表示され呼び出しに失敗しております。

<ComVisible(True), Guid("2ECC690C-9869-47AD-9DF7-58CF0E44917F")>
Public Structure Structure1
Dim Str1 As String
Dim Str2 As String
Dim Str3 As String
End Structure

Declare Function Test1 Lib "Test.DLL" <MarshalAs(UnmanagedType.SafeArray, SafeArraySubType:=VarEnum.VT_RECORD)> ByVal oStructure() As Structure1) As Integer


お手数ですがお教え頂ければと思います。


以上、宜しくお願い致します。
引用返信 編集キー/
■75591 / inTopicNo.4)  Re[3]: VB.net⇒VC++6.0のVoid型に構造体配列参照渡
□投稿者/ 魔界の仮面弁士 (283回)-(2015/04/10(Fri) 14:16:09)
No75590 (とら さん) に返信
> AssemblyInfo.vbに追加する際にComVisivleおよびGuidを複数回適用することはできないというエラーが表示され設定できませんでした。
Guid を複数適用するのではなく、それぞれに個別に適用するということです。

構造体が複数あれば、それぞれの構造体に一つずつ適用します。
DLL が複数あれば、それぞれのアセンブリに一つずつ適用します。


> AssemblyInfo.vbは前回築城したもののみとし、
一度作成した VB.NET のアセンブリにたいし、GUID を変更するべきかどうかは、
VB6 のコンパイルオプション(コンポーネント タブ)にあった
  ・互換なし
  ・バイナリ互換
と同様に考えてみて下さい。
https://support.microsoft.com/en-us/kb/161137/ja


> 今回の構造体にのみ新規作成したGuidを設定してDeclareにもマーシャリングを追加致しましたが、
構造体フィールドに MarshalAs 属性が抜けているからではないでしょうか。

文字列のマーシャリングについては、No75561 および前回のスレッドで紹介した URL を参照してみて下さい。
引用返信 編集キー/
■75608 / inTopicNo.5)  Re[4]: VB.net⇒VC++6.0のVoid型に構造体配列参照渡
□投稿者/ とら (17回)-(2015/04/10(Fri) 18:31:43)
No75591 (魔界の仮面弁士 さん) に返信

>>AssemblyInfo.vbに追加する際にComVisivleおよびGuidを複数回適用することはできないというエラーが表示され設定できませんでした。
> Guid を複数適用するのではなく、それぞれに個別に適用するということです。
> 
> 構造体が複数あれば、それぞれの構造体に一つずつ適用します。
> DLL が複数あれば、それぞれのアセンブリに一つずつ適用します。

構造体毎にのみ設定するようにしました。


> 構造体フィールドに MarshalAs 属性が抜けているからではないでしょうか。
下記のように追加致しましたが、1番目の配列の内容すら受け渡せていませんでした

<ComVisible(True), Guid("2ECC690C-9869-47AD-9DF7-58CF0E44917F")>
Public Structure Structure1
 <MarshalAs(UnmanagedType.BStr)> Dim Str1 As String
 <MarshalAs(UnmanagedType.BStr)> Dim Str2 As String
 <MarshalAs(UnmanagedType.BStr)> Dim Str3 As String
End Structure

他にも、UnmanagedTypeに対して「TBStr」「LPStr」「LPTStr」「HString」「AnsiBStr」も指定してみましたが、受け渡しに失敗したり値が入らなかったりといった様子。


以上、引き続き宜しくお願い致します。




引用返信 編集キー/
■75611 / inTopicNo.6)  Re[5]: VB.net⇒VC++6.0のVoid型に構造体配列参照渡
□投稿者/ とら (18回)-(2015/04/10(Fri) 21:15:11)
追記

構造体宣言部分を

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)>
<ComVisible(True), Guid("2ECC690C-9869-47AD-9DF7-58CF0E44917F")>
Public Structure Structure1
<MarshalAs(UnmanagedType.BStr)> Dim Str1 As String
<MarshalAs(UnmanagedType.BStr)> Dim Str2 As String
<MarshalAs(UnmanagedType.BStr)> Dim Str3 As String
End Structure

とすると、VCから正常に処理が終了したと戻ってくるものの値は反映されておらず。

むむーん
引用返信 編集キー/
■75612 / inTopicNo.7)  Re[6]: VB.net⇒VC++6.0のVoid型に構造体配列参照渡
□投稿者/ とら (19回)-(2015/04/13(Mon) 10:10:09)
ひどいオチでしたが解決したのでご報告を。

VB側とVC側の構造体内の変数名が異なる為にマーシャリングがうまくいっていなかったという結果でした。

マーシャリングしてもうまく行かない場合は見直してみたほうが良さそうです。

以上、お騒がせ致しました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -