- - PR -
VB.NETの構造体配列の、VC++DLLへの受け渡し方法
1
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2008-03-12 20:52
はじめまして。
現在、VB6&VC++6で開発していたアプリケーションを、Visual Studio2005(以降"VS2005")への移植作業を行っていますが、VB.NET→VC++へのマーシャライズがうまく行えず、困っています。 解決方法をご存知の方がいれば、ご教授願います。 <前提> 実行ファイル:VB6→VB.NET2005(8.0) DLLファイル:VC++6→VC++2005(8.0) ※「/clr」オプションは未指定。 (intel MKLライブラリがリンクエラーになってしまうため) <問題点> VB.NET上で定義した構造体(ユーザ定義型)の配列が、VC++で作成したアンマネージドDLLとの受け渡しでエラーになる。 <コード> **VB.NET** Imports System.Runtime.InteropServices <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Ansi)> _ Public Structure AAA Dim aaa As Integer Dim bbb As Integer Dim ccc As Double Dim ddd As Double End Structure Public a_dat() As AAA Private Declare Function AAA_FUNC Lib "TARGET.dll" Alias "aaa_func" (ByRef RecCnt As Integer, ByRef a_dat() As AAA) As Integer Public Function func1() As Integer Public RecCnt As Integer Public ret As Integer 'RecCntにレコード件数を取得後、確保 ReDim a_dat(RecCnt - 1) 'a_datにレコードセット 'アンマネージドDLLを呼び出し ret = AAA_FUNC(IssReCount, a_dat) If ret <> 0 Then func1 = ret Exit Function End If End Function **VC++** __declspec(dllexport) int __stdcall aaa_func(long *,LPSAFEARRAY *); typedef struct{ long aaa; long bbb; double ccc; double ddd; } AAA_C; vector<AAA_C> a_data; __declspec(dllexport) int __stdcall aaa_func(long *m_row,LPSAFEARRAY *va_data) { long idx; long lb, ub; long i; vector<AAA_C>& vdata=a_data; LPSAFEARRAY psa; a_data.reserve(*m_row); psa = *va_data; if(psa->cDims != 1) { // psa->cDims : 2 となってしまう? return <エラーコード>; } SafeArrayLock(psa); SafeArrayGetLBound(psa, 1, &lb); SafeArrayGetUBound(psa, 1, &ub); if(lb != 0 || ub != (*m_row)-1){ SafeArrayUnlock(psa); return <エラーコード>; } for( idx = lb, i=0; idx <= ub; idx++, i++ ){ SafeArrayGetElement(psa, &idx, &vdata[i]); } SafeArrayUnlock(psa); return 0; } 以上、よろしくお願いします。 | ||||||||
|
投稿日時: 2008-03-12 23:15
このページとかどうでしょうか。 TestArrayOfStructsあたりがご所望のものかと存じます。 http://msdn2.microsoft.com/ja-jp/library/hk9wyw21.aspx P/Invokeで特に指定しなかった場合、配列はSafeArrayにはなりません。 (MarshalAsで指定すればなるかもしれませんが、未確認) | ||||||||
|
投稿日時: 2008-03-13 16:25
Azuleanさん、貴重な情報ありがとうございました。
本日、上記を参考にして試してみました。 一見、うまく行きそうにも思えたのですが、期待した結果にはなりませんでした・・・。 SafeArrayGetLBound()/SafeArrayGetUBound()が正しく実行できませんでした。 (下記の例ならlb : 0、ub : 2のはず・・・。
正直、MKLライブラリ部分を残して、C#に切り替えたほうが・・・とも考えたのですが、 C#は未経験にも関わらず、その場合は20Kステップのプログラムを2週間で対応しろとか言われてしまって・・・ 出来れば、VC++のまま行きたいと考えているので、思いつきでも構わないので情報を頂けると助かります! よろしくお願いします。 | ||||||||
|
投稿日時: 2008-03-14 00:18
昨日、私が示したページのC++側のコード(宣言)をお読みになられましたか?
あのサンプルはSAFEARRAYではなく、一般的なC言語配列になりますよ。
| ||||||||
|
投稿日時: 2008-03-14 16:52
Azuleanさん、度々ありがとうございます。
申し訳ありませんでした。 構造体を配列を、出来ればVC++側には手を入れないで受け渡ししたいと考えていたので、勝手に先入観を持ってしまいました。 確かに、サンプルのVC++の宣言部はSAFEARRAYを使用していませんね。 元々のコードを、下記のように変更して実行したところ、VB.NET側で定義/セットした構造体の配列を、VC++側で受け取れるようになれました。
元々の希望とは違い、多少VC++側にも手を入れる必要がありますが、何とか目的を果たせそうです。 ありがとうございました! |
1