SAFEARRAY関連の関数で相談 – プログラミング – Home

SAFEARRAY関連の関数で相談
 
通知
すべてクリア

[解決済] SAFEARRAY関連の関数で相談

固定ページ 1 / 2

ナオーバ
 ナオーバ
(@ナオーバ)
ゲスト
結合: 23年前
投稿: 187
Topic starter  

SafeArrayCreateVector や SafeArrayAccessData や SafeArrayUnaccessData は
COMのインターフェース内でしか使用できないのでしょうか?

lpsfArray = SafeArrayCreateVector(VT_BSTR, 0, sArray.GetSize());
if(NULL == lpsfArray)
{
return FALSE;
}

hRet = SafeArrayAccessData(lpsfArray, (void HUGEP **)&lpBSTRData);
if(FAILED(hRet))
{
return FALSE;
}

for (i = 0; i < sArray.GetSize(); i++)
{
lpBSTRData[i] = sArray.GetAt(i).AllocSysString();
}
SafeArrayUnaccessData(lpsfArray);
lpsfArrayはSAFEARRAYのポインタ
sArrayはCStringArray
lpBSTRDataはBSTRのポインタ

この処理をCOMのインターフェース内で実行した場合は予定の動作の
CStringArrayのデータをSAFEARRAYにコピーできます。
しかし、この処理をCOMのprivateな内部関数にすると動作しません。

実際この処理を4つのCStringArrayに対して行いたいので関数化したのですが、
無理なのでしょうか?

WIN2000SP4/VC++6.0SP5/MFC使用

よろしくお願いします


引用未解決
トピックタグ
渋木宏明(ひどり)
 渋木宏明(ひどり)
(@渋木宏明(ひどり))
ゲスト
結合: 23年前
投稿: 196
 

>SafeArrayCreateVector や SafeArrayAccessData や SafeArrayUnaccessData は
>COMのインターフェース内でしか使用できないのでしょうか?

そんなことはありません。

>しかし、この処理をCOMのprivateな内部関数にすると動作しません。

どんなコードを書いて、どんな状況になってしまっているのでしょう?


返信引用
ナオーバ
 ナオーバ
(@ナオーバ)
ゲスト
結合: 23年前
投稿: 187
Topic starter  

元ソースを参考にいろいろ試した結果、期待通りに動くものが完成したのですが、
SAFEARRAYの基本的な使用法がわからないのでソースの意味がわかりません。

以下にソースの抜粋
idlファイル内に以下のメンバがある構造体STXXXXを定義し
SAFEARRAY(BSTR) lpsfaName; <----(1)
このSTXXXXのポインタを引数とするCOMのインターフェース
GetXXX(LPSTXXXX lpStXxxx)を作成しました。
このGetXXXで共通関数をよびCStringArrayにデータをセットします。
そしてCOMのprivateな内部関数SetArrayDataに渡し

 SetArrayData(saName, &lpStXxxx->lpsfaName); <----(2)

SAFEARRAYにCStringArrayのデータをSAFEARRAYにコピーしています。

BOOL COAMaterialDataCom::SetArrayData(CStringArray& szArray, SAFEARRAY**
lpsfArray) <----(3)
{
BSTR* lpBSTRData = NULL;
HRESULT hResult;

if( szArray.GetSize() != 0 )
{
*lpsfArray = SafeArrayCreateVector(VT_BSTR, 0, szArray.GetSize());
if(NULL == lpsfArray) return FALSE;

hResult = SafeArrayAccessData(*lpsfArray, (void HUGEP **)&lpBSTRData);
if(FAILED(hResult)) return FALSE;

for (int i = 0; i < szArray.GetSize(); i++)
lpBSTRData[i] = szArray.GetAt(i).AllocSysString();

SafeArrayUnaccessData(*lpsfArray);
}
return TRUE;
}

わからない事
1.(1)の定義は何?
 SAFEARRAYは構造体のハズで(BSTR)は何をしている?マクロ?
2.(1)の定義を仮にSAFEARRAYのポインタ宣言をしているとすると、
 (3)のSAFEARRAY**の意味はわかりますが、*lpsfArrayはポインタを指しているはずなのに
 SafeArrayCreateVectorの戻り値はポインタではないのでなぜ問題ないの?
3.このCOMはVBから呼び出した時に期待通りの動作をします
 VB側ではCOMに渡す引数を作成する時にlpsfaNameには何もセットしていません。
 (1)の定義を仮にSAFEARRAYのポインタ宣言をしているとすると実体を作成してセット
 しないとまずいはずなのになぜうまく機能しているの?

ネットやMSDNでSAFEARRAYで検索してもなかなかみつかりませんでした。
何かここでわかるよなどないでしょうか?

よろしくお願いします


返信引用
そらぱ
 そらぱ
(@そらぱ)
ゲスト
結合: 22年前
投稿: 14
 

以前私も悩みました。わかる部分だけ書きます。
(トンチンカンだったらごめんなさい)

> 1.(1)の定義は何?
>  SAFEARRAYは構造体のハズで(BSTR)は何をしている?マクロ?

これはidlファイルなのでMIDLの記述です。
SAFEARRAY(BSTR)でBSTRのSAFEARRAY*をあらわしています。
コンパイルするとSAFEARRAY*として扱われます。

> 2.(1)の定義を仮にSAFEARRAYのポインタ宣言をしているとすると、
>  (3)のSAFEARRAY**の意味はわかりますが、*lpsfArrayはポインタを指しているはずなの

>  SafeArrayCreateVectorの戻り値はポインタではないのでなぜ問題ないの?

SafeArrayCreateVector は SAFEARRAY* ですよね?
問題ないと思います。

> 3.このCOMはVBから呼び出した時に期待通りの動作をします
>  VB側ではCOMに渡す引数を作成する時にlpsfaNameには何もセットしていません。
>  (1)の定義を仮にSAFEARRAYのポインタ宣言をしているとすると実体を作成してセット
>  しないとまずいはずなのになぜうまく機能しているの?

SAFEARRAYを関数SetArrayData内で作成してlpsfArrayに返すという動作なので、
実態を用意しなくてもいいのだと思います。
逆に実態があった場合は、SafeArrayDestroyなどで削除しなければならないはずです。


返信引用
ナオーバ
 ナオーバ
(@ナオーバ)
ゲスト
結合: 23年前
投稿: 187
Topic starter  

回答ありがとうございます。
>SafeArrayCreateVector は SAFEARRAY* ですよね?
MSDNを見ると
SAFEARRAY SafeArrayCreateVector(
VARTYPE vt,
long lLbound,
unsigned int cElements
);
のようになっており、ポインタではないのです。
MSDNが間違いなのかな?

>逆に実態があった場合は、SafeArrayDestroyなどで削除しなければならないはずです。
malloc等の場合はポインタが返ってきて使用した後freeします。
SafeArrayCreateVectorの場合はいらないのですか?

質問ばかりですが宜しくお願いします。


返信引用
そらぱ
 そらぱ
(@そらぱ)
ゲスト
結合: 22年前
投稿: 14
 

> MSDNを見ると
> SAFEARRAY SafeArrayCreateVector(
> VARTYPE vt,
> long lLbound,
> unsigned int cElements
> );
> のようになっており、ポインタではないのです。
> MSDNが間違いなのかな?

あれ?
私の使っているMSDN(2001年10月 日本語)では SAFEARRAY* になってますよ。
説明文も、
 Return Value
  Points to the array descriptor, or Null if the array could not be created.
です。
(Platform SDK: Automation内です。これ以降のMSDNは .NET なので使ってません)


返信引用
ナオーバ
 ナオーバ
(@ナオーバ)
ゲスト
結合: 23年前
投稿: 187
Topic starter  

そうなんなんですね、こ
こちらで使用しているものは付属していた1998/7/19版で相当古いようです。

SafeArrayCreateVectorはポインタを返却する事はわかりました。
すると、idl内での定義もポインタなので実体はどこにあるんでしょう?
難しいです


返信引用
渋木宏明(ひどり)
 渋木宏明(ひどり)
(@渋木宏明(ひどり))
ゲスト
結合: 23年前
投稿: 196
 

実体って、SAFEARRAY の実体のことですよね?
メモリ上でしょ?

SAFEARRAY の宣言は、VC++ のヘッダ(=OLE 関係のどれか)を検索すれば出てきます。


返信引用
ナオーバ
 ナオーバ
(@ナオーバ)
ゲスト
結合: 23年前
投稿: 187
Topic starter  

インストールしていたPlatform SDKの最新版のヘルプにSafeArrayCreateVectorがありました
ポインタで返却されていました。

>実体って、SAFEARRAY の実体のことですよね?
>メモリ上でしょ?
実体って表現がよくないでした。わからないのは
SafeArrayCreateVectorは引数に指定した個数(固定)の一次元配列を作成し、
このポインタをかえす。malloc等の場合はfreeをするのですが
SafeArrayCreateVectorはいつメモリを解放しているのでしょうか?
この点を意識しなく使用できるのでセーフ(安全)配列?

何度もすみません、よろしくい願い致します


返信引用
そらぱ
 そらぱ
(@そらぱ)
ゲスト
結合: 22年前
投稿: 14
 

SafeArrayDestroyで削除する必要があるはずです。
ただし、VB側に渡した後はVBが面倒見てくれていると思います。


返信引用
ナオーバ
 ナオーバ
(@ナオーバ)
ゲスト
結合: 23年前
投稿: 187
Topic starter  

>ただし、VB側に渡した後はVBが面倒見てくれていると思います
ここら辺がわからないのです。

VB側では何をしているのでしょう?
VBが勝手に解放してくれるのでしょうか?

VBの質問になってしまいましたがよろしくお願いします。


返信引用
渋木宏明(ひどり)
 渋木宏明(ひどり)
(@渋木宏明(ひどり))
ゲスト
結合: 23年前
投稿: 196
 

VBに引き渡したオブジェクトの解放は、VBがやってくれます。

SAFEARRAY だけでなく、文字列(=BSTR)もそうだし、オブジェクトインスタンスの参
照もそうです。

# むしろ、SAFEARRAY や BSTR も「一種のオブジェクトである」と考えた方がすっきり
するかもしれません。


返信引用
ナオーバ
 ナオーバ
(@ナオーバ)
ゲスト
結合: 23年前
投稿: 187
Topic starter  

こまかい事ですが最終確認です。

VBにはSafeArrayCreateVectorした配列のポインタが渡り、
SafeArrayCreateVectorで確保したメモリ領域はVBが解放してくれる。
VBのプログラムを書いている人ではなくVBが解放してくれる。

したがって、最初に提示したソースはおかしなことはしていない。

これで最後にします。よろしくお願いします。


返信引用
渋木宏明(ひどり)
 渋木宏明(ひどり)
(@渋木宏明(ひどり))
ゲスト
結合: 23年前
投稿: 196
 

>VBにはSafeArrayCreateVectorした配列のポインタが渡り、
>SafeArrayCreateVectorで確保したメモリ領域はVBが解放してくれる。
>VBのプログラムを書いている人ではなくVBが解放してくれる。

その通りです。

>したがって、最初に提示したソースはおかしなことはしていない。

ソースの方は、異常が無いかどうか断言出来るほどよく見てません。


返信引用
そらぱ
 そらぱ
(@そらぱ)
ゲスト
結合: 22年前
投稿: 14
 

気になるのは *lpsfArray が示すところにすでに SAFEARRAY の実態があったときですね。
SafeArrayCreateVector の前に開放しないとリークになるかな?
(VBから渡された場合ってどうなるんだろう?やったことないです。)


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました