VB2010からVCが受け取る配列のアドレスについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ousi
記事: 6
登録日時: 9年前

VB2010からVCが受け取る配列のアドレスについて

#1

投稿記事 by ousi » 9年前

初めまして、よろしくお願いします。

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バイトというのはどういった理由からなのでしょうか?

アバター
いわん
記事: 32
登録日時: 9年前

Re: VB2010からVCが受け取る配列のアドレスについて

#2

投稿記事 by いわん » 9年前

SAFEARRAY型というのが関係しているかも?
詳しくないのでふわっとした情報で申し訳ないですが^^;

ousi
記事: 6
登録日時: 9年前

Re: VB2010からVCが受け取る配列のアドレスについて

#3

投稿記事 by ousi » 9年前

sizeof(SAFEARRAY)で調べたところ、確かに24バイトであると認識できました。
理由はこれなのかもしれません。

その後の調査により、マーシャリングするなどが必要なようですね。配列をやり取りする箇所については、以前の方法とは別の方法が必要であると認識できたので、この箇所を修正する方向で考えたいと思います。
ありがとうございました。

ousi
記事: 6
登録日時: 9年前

Re: VB2010からVCが受け取る配列のアドレスについて

#4

投稿記事 by ousi » 9年前

https://support.microsoft.com/ja-jp/kb/207931
上記の内容が今回の疑問点を解消してくれそうなので、示しておきます。

ousi
記事: 6
登録日時: 9年前

Re: VB2010からVCが受け取る配列のアドレスについて

#5

投稿記事 by ousi » 9年前

あれやこれやと悩んで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側に渡す方法はないでしょうか?

ousi
記事: 6
登録日時: 9年前

Re: VB2010からVCが受け取る配列のアドレスについて

#6

投稿記事 by ousi » 9年前

最初の質問時より、かなり認識が変わってきて、回答もなかなか付かないようなので、改めて書き直して別途質問しようと思います。
こちらはひとまず閉じます。

ousi
記事: 6
登録日時: 9年前

Re: VB2010からVCが受け取る配列のアドレスについて

#7

投稿記事 by ousi » 9年前

閉じた予定だったのですが、その後、質問しなおす前に解決しました。
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);
}
VB2010側でObjectからDirectCastしてlong型配列に値を設定し、それを出力したところ、OCX側で設定した値を表示することができました。
後は、引数に設定されている配列要素数などをチェックすればクリアになるのかなと思います。

閉鎖

“C言語何でも質問掲示板” へ戻る