- PR -

VC++のDLLからVB.NETへ構造体を渡すには

1
投稿者投稿内容
ちばじん
会議室デビュー日: 2007/08/14
投稿数: 7
投稿日時: 2007-10-01 19:14
VC++のDLLからVB.NETへの構造体を渡しかたについて困っています。

環境はVC++2003、VB.NET 2003です。

コンパイルは通るのですが実行しても値が表示されません。。。

いろいろ調べたところString オブジェクトは、不変 (読み取り専用)であるため値を変更できないらしいです。
対応策としてSystem.Text.StringBuilder クラスを使用するといいらしいのですが構造体ではSystem.Text.StringBuilderが使えません。。。

何かいい解決方法はないでしょうか??


VC++側 −−−−−−−−−−−−−−−−−−−−−−−−−−−

typedef struct _ATT_INFO {
BSTR NUMBER;
BSTR PRODUCT_CODE;
BSTR RUIBETU;
} ATT_INFO ;

bool __stdcall GetAttInfo( ATT_INFO attInfo){

AFX_MANAGE_STATE( AfxGetStaticModuleState() ) ;

attInfo = GetAttInfo();

return true;
}

ATT_INFO GetAttInfo(){
ATT_INFO mAttInfo;

CString mNumber = "aaa";
CString mProductCode = "bbb";
CString mRuibetu = "ccc";

mAttInfo.NUMBER = mNumber.AllocSysString();
mAttInfo.PRODUCT_CODE = mProductCode.AllocSysString();
mAttInfo.RUIBETU = mRuibetu.AllocSysString();

return mAttInfo;
}

−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

VB.NET側 −−−−−−−−−−−−−−−−−−−−−−−−−−

Private Declare Auto Function GetAttInfoLib "hoge.dll" (ByRef mAttInfo As ATT_INFO) As Boolean

Public Structure ATT_INFO
Dim NUMBER As String
Dim PRODUCT_CODE As String
Dim RUIBETU As String
End Structure

Private Sub BUTTON1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BUTTON1.Click

Dim wAttInfo As ATT_INFO
wAttInfo = New ATT_INFO

GetAttInfo(wAttInfo)

MsgBox(wAttInfo.NUMBER)
MsgBox(wAttInfo.PRODUCT_CODE)
MsgBox(wAttInfo.RUIBETU)

End Sub
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2007-10-01 22:07
んーと、「String の値」ってのは、例えば Dim a As String = "test" と言うときの test と言う文字列そのもので、値を変更できないってのはこの "test" と言う文字列を "tEst" に変更できないって意味です。取得するだけなら a(1) で e と言う文字が取れますが、a(1) に対して代入はできません。
でも参照先そのものを変更する、つまり a = "tEst" とすることはできますよね。
今回の場合、C++ コードは参照先そのものの変更と同じように、文字列変数そのものに代入しています。ですから、String の値の変更不可はこのコードでは問題になりません。

C++ コード内の GetAttInfo 関数は、引数が ATT_INFO 型です。
で、その ATT_INFO 型は構造体型そのものですから、結局この関数は構造体の値渡しになっています。
翻って VB の方の Declare 宣言を見ると、ByRef mAttInfo As ATT_INFO と指定しています。ByRef ですから、当然参照渡し、マーシャリングの際はポインタとして扱われます。
これが受け取れない理由です。

で、C++ の方で BSTR を使っているのに注意しなければなりません。
BSTR はコードを見れば分かるとおり、呼び出し先(DLL = C++ コード内)でメモリが確保されます。このまま放っておいたら解放の機会を失ってリークするでしょう(一般に BSTR のメモリの解放の責任は呼び出し側にあります)。
.NET の相互運用機構は、それが BSTR であると知っていれば、アンマネージドの文字列をマネージドの文字列(つまり String)に変換する際、ついでにその領域を解放してくれます。
アンマネージドでの文字列型を .NET に知らせるのが MarshalAs 属性と UnmanagedType 列挙体です。
詳しくは文字列に対する既定のマーシャリングをご覧ください。
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2007-10-02 00:03
なんかもやもやすると思ったら。
そもそも構造体を値渡ししてたら呼び出し元は呼び出し先の処理結果を返値以外で受け取ることができないんでした。
と言うことで何かがおかしいです。
ちばじん
会議室デビュー日: 2007/08/14
投稿数: 7
投稿日時: 2007-10-02 11:36
引用:

Hongliangさんの書き込み (2007-10-02 00:03) より:
なんかもやもやすると思ったら。
そもそも構造体を値渡ししてたら呼び出し元は呼び出し先の処理結果を返値以外で受け取ることができないんでした。
と言うことで何かがおかしいです。



・・・何かとはなんでしょうか??

また、VC++のDLLからVB.NETへ構造体を渡すいい方法はないでしょうか??
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2007-10-02 11:56
コードから掲示板書き込むときに写し間違いがあったんじゃないかな、と思ったんですが。

普通に C++ で書いたり VB で書いたりするのと変わりません。
C++ 同士で同じことを実現しようとしたときに書くように書けばいいです。
VB の方も同様。
1

スキルアップ/キャリアアップ(JOB@IT)