初めまして、よろしくお願いします。
VC++6で作成されたOCXをVC2010用に修正して、そのOCXをVB2010で使用しています。
その際、配列の最初の要素のアドレスを受け取っているのですが、その次の要素のアドレスをどのように取得すればよいのか、わかりません。
VC++6では、以下のように処理していました。
// lXとlYに、配列要素の先頭アドレスが渡ってきます。
// lX[0] = 1000、lX[1] = 2000、lY[0] = 1500、lY[1] = 2500のようにVB側でしている場合、
// Searchs( lx(0), ly(0) ) のようにして呼び出しています。
short Searchs(long FAR* lX, long FAR *lY)
{
CPoint Pos1, Pos2; // Pos1に要素0、Pos2に要素1の各値を設定したい
Pos1.x = *lX;
Pos1.y = *lY;
lX++;
lY++;
Pos2.x = *lX;
Pos2.y = *lY;
// 以下の処理は省略
}
上記処理だと、次の要素のアドレスが4バイト先にあることになります。以前VB6でこのVC++6のOCXを使用していた場合は問題ありませんでした。VC2010ではこのような処理では次の要素は取得できないということでよろしいでしょうか?
また、配列の最初の要素と次の要素のアドレスを比べたところ、最初の配列から24バイト先に次の配列の要素がありました。この24バイトというのは固定でしょうか?そして、24バイトというのはどういった理由からなのでしょうか?
VB2010からVCが受け取る配列のアドレスについて
Re: VB2010からVCが受け取る配列のアドレスについて
SAFEARRAY型というのが関係しているかも?
詳しくないのでふわっとした情報で申し訳ないですが^^;
詳しくないのでふわっとした情報で申し訳ないですが^^;
Re: VB2010からVCが受け取る配列のアドレスについて
sizeof(SAFEARRAY)で調べたところ、確かに24バイトであると認識できました。
理由はこれなのかもしれません。
その後の調査により、マーシャリングするなどが必要なようですね。配列をやり取りする箇所については、以前の方法とは別の方法が必要であると認識できたので、この箇所を修正する方向で考えたいと思います。
ありがとうございました。
理由はこれなのかもしれません。
その後の調査により、マーシャリングするなどが必要なようですね。配列をやり取りする箇所については、以前の方法とは別の方法が必要であると認識できたので、この箇所を修正する方向で考えたいと思います。
ありがとうございました。
Re: VB2010からVCが受け取る配列のアドレスについて
https://support.microsoft.com/ja-jp/kb/207931
上記の内容が今回の疑問点を解消してくれそうなので、示しておきます。
上記の内容が今回の疑問点を解消してくれそうなので、示しておきます。
Re: VB2010からVCが受け取る配列のアドレスについて
あれやこれやと悩んで3週間、やっとOCX側でVB2010の配列の値を受け取ることができました。
ディスパッチマップの該当引数をVTS_VARIANTとし、VB2010からは、lX[0]ではなくlXを渡すようにします。
受け側のOCXでは、
Searchs([in] VARIANT lX)で定義し、メソッドは、
Searchs(VARIANT *lX)としました。
すると、lXの配列の値がOCX側で受け取ることができました。
ただ、この方法では、OCX側からVB2010側の配列に値を設定することができません。
Searchs([in,out] VARIANT* lX)で定義すればいけるかなと思いましたが、これだけではうまくいきませんでした。
配列の値をOCXからVB2010側に渡す方法はないでしょうか?
ディスパッチマップの該当引数をVTS_VARIANTとし、VB2010からは、lX[0]ではなくlXを渡すようにします。
受け側のOCXでは、
Searchs([in] VARIANT lX)で定義し、メソッドは、
Searchs(VARIANT *lX)としました。
すると、lXの配列の値がOCX側で受け取ることができました。
ただ、この方法では、OCX側からVB2010側の配列に値を設定することができません。
Searchs([in,out] VARIANT* lX)で定義すればいけるかなと思いましたが、これだけではうまくいきませんでした。
配列の値をOCXからVB2010側に渡す方法はないでしょうか?
Re: VB2010からVCが受け取る配列のアドレスについて
最初の質問時より、かなり認識が変わってきて、回答もなかなか付かないようなので、改めて書き直して別途質問しようと思います。
こちらはひとまず閉じます。
こちらはひとまず閉じます。
Re: VB2010からVCが受け取る配列のアドレスについて
閉じた予定だったのですが、その後、質問しなおす前に解決しました。
VS2015で一から簡単なOCXをサンプルで作って確認したところ、重要なヒントが表示され、解決しました。
VB2010側でObjectからDirectCastしてlong型配列に値を設定し、それを出力したところ、OCX側で設定した値を表示することができました。
後は、引数に設定されている配列要素数などをチェックすればクリアになるのかなと思います。
VS2015で一から簡単なOCXをサンプルで作って確認したところ、重要なヒントが表示され、解決しました。
void Searchs(VARIANT FAR* lX)
{
VARIANT *va;
if ((*lX).vt == (VT_VARIANT | VT_BYREF)) {
va = (*lX).pvarVal;
} else {
va = &(*lX);
}
SAFEARRAY *psa;
if (va->vt & VT_BYREF) {
psa = *va->pparray;
} else {
psa = va->parray;
}
long *ldata;
HRESULT hr = SafeArrayAccessData(psa, (void**) &ldata);
// ここで、ldataにVB2010で設定した配列が受け取れたことを確認
// 次に、以下のデータを設定してVB2010側で受け取れるか確認する
ldata[0] = 1000;
ldata[1] = 2000;
SafeArrayUnaccessData(psa);
}
後は、引数に設定されている配列要素数などをチェックすればクリアになるのかなと思います。