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

わんくま同盟

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

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


■91199 / )  VB.NETからC++のdll関数への参照渡しについて
□投稿者/ まる (1回)-(2019/06/06(Thu) 07:46:56)

分類:[.NET 全般] 

分かりづらいタイトルで申し訳ございません。はじめての投稿になるため至らない点もあるかと思いますが、よろしくお願いいたします。
VisualStudio2013 Framework4.0を使用しております。

元々vb6で作られていたソースをvb.netで作り直すことになりました。
元のvb6ではc++で作られたdllを参照しており、まず、今回問題となる部分はVB6では大体以下のように記述されておりました。

(VB6)
sub Sample()
Dim intArray(0 To 999) As Integer
Dim objTest As New TestClass
Dim lngReturn As Long
Dim lngSize As Long = 368

(省略) ※省略した中でintArrayの全ての要素に0を設定しています。

lngReturn = objTest.AAA(intArray(0),lngSize)
end sub

上記で生成した「TestClass」が、C++のdllにあるクラスです。
C++での記述はおおまかには以下のようになっています。

(C++)
class TestClass{
Long AAA(Short Far* sAdd,Short sSize) {
Short bufSize = sSize * 2;
Char *buf = (Char *)sAdd;
Char *strValue;

memset(buf,0,bufSize);

(省略)※strValueに値を格納;

memcpy(buf,strValue,bufSize);


Char chStr[256];

wsprintf(chStr , "Add : %d, Value : %d", sAdd, *sAdd);
MessageBox(NULL , chStr , TEXT("Test") , MB_OK);

Return bufSize;
}
}

上記のメッセージボックスをVB6で実行したときに表示すると、
Add : (9ケタの可変の数字), Value : -12345
と表示されます。

vb6でのIntegerはVb.NETではShort、vb6でのLongはVB.NETではIntegerだと、Webを調べてそのような情報を見つけたので、それらを踏まえてVB.Netでは以下のように記述いたしました。

(VB.Net)
sub Sample()
Dim shtArray(999) As Short
Dim objTest As New TestClass
Dim intReturn As Integer
Dim intSize As Integer = 368

(省略) ※省略した中でshtArrayの全ての要素に0を設定しています。

intReturn = objTest.AAA(shtArray(0),intSize)
'※visualstudioでAAAにカーソルをあてて引数の型を確認したところ、
' AAA(Byref sBuf As Short,ByVal sSize As Short) As Integer
' と表示されておりました。

Msgbox(intReturn)
end sub


これを実行したところ、objTest.AAAのreturn前に表示されるメッセージボックスには、
Add : (7ケタの可変の数字), Value : -12345
と表示され、その直後、returnの部分でアプリが強制終了しました。この強制終了をなんとか解消したいです。VB6ではなぜ上手くいき、vb.netにした途端にダメになったのかも知りたいです。
(vb.netやC++のソースにTryを記述しましたが、何も例外を捕捉することができませんでした)

まず、VB6ではC++の関数に渡ったアドレスは9ケタであったのに対して、VB.Netの場合は7ケタになっているのが気になりました。
また、vb.netでは動的に変数のアドレスが変わる、と聞いたことがあるため、その点も原因の一つなのではないか、とは少し考えております。

AAA内のmemset,memcpyなどが怪しいと思い、試しにその2行だけコメントアウトしたところ、強制終了しなくなったため(逆に、その2行のコメントアウトを解除すると強制終了しました)、その2行に何かあるのではないかと考えておりますが、C++のソースコードは極力変えたくないです。
また、VB6ではなぜ問題なく、vb.netではダメなのか、なぜreturnの時にエラーが発生するのかがわかりません。

C++dll(objTest)の全ての関数やプロパティが呼べないわけではなく、
引数に参照渡しを行わない関数やプロパティをvb.netから呼び出した際には、VB6と同じように問題なく動作しているのですが、
上記のような配列変数の参照渡しを行う関数に対してはエラーが発生しております。
そのため、アドレスが固定できていないのだろうか、と考え、以下のようにして固定して試みましたが、方法がよくなかったのか同じようにreturnで強制終了してしまいました。

(VB.Net アドレス固定)
sub Sample()
Dim shtArray(999) As Short
Dim objTest As New TestClass
Dim intReturn As Integer
Dim intSize As Integer = 368
Dim objHandle As GCHandle = GCHandle.Alloc(shtArray(0),GCHandleType.Pinned)
Dim intPinned As Intptr = objHandle.AddrOfPinnedObject()

(省略) ※省略した中でshtArrayの全ての要素に0を設定しています。

intReturn = objTest.AAA(shtArray(0),intSize)
Msgbox(intReturn)

objHandle.Free()
end sub

となると、浅学ながら、やはり配列を参照渡しにしている部分が問題ではないか、とは思うのですが、改善策も何も目処が立っておりません。
どんな些細な情報でもよいので、どうかご指南いただけないでしょうか。
説明不足がございましたら、恐れ入りますがご指摘いただけますと幸いです。
何卒よろしくお願いいたします。
返信 編集キー/


管理者用

- Child Tree -