VARIANT配列のデータを解凍するには?

解決


kty  2006-12-01 18:11:27  No: 63759

よろしくお願いします。
VARIANT型の配列(vaData)を解凍させたいのですが、ソースなど
わかりますでしょうか?
VC6.0でのMFCなのですが!


シャノン  2006-12-01 18:15:31  No: 63760

全くわかりません。
解凍ってことは、何らかの形式で圧縮されているのですか?
圧縮形式がわからないことにはどうにもなりません。
また、何故それがVARIANT型なのかという疑問も…


Blue  2006-12-01 18:15:44  No: 63761

解凍とは?

VARIANT型配列とは普通に

VARIANT hoge[10];

みたいなものでしょうか?
それとも

VARIANT hoge;

自体が配列なんでしょうか?


kty  2006-12-01 18:47:34  No: 63762

VARIANT hoge;
が配列になっている状態です。

今のところSafeArrayCreate();や
Uncompress();を使うのかなと?


Blue  2006-12-01 18:56:05  No: 63763

>VARIANT hoge;
>が配列になっている状態です。
もうすでに配列になっているのにSafeArrayCreateは使う必要がないでしょう。

これをどうしたいのでしょうか?
「解凍する」の説明がないのでどうしようもできませんけど。

予想)
// BSTR型配列をCStringArrayに変換する
CStringArray ary;

if ( hoge.vt & ( VT_ARRAY | VT_BSTR | VT_BYREF ) ) // VT_BYREFは微妙
{
    LONG lb, ub;

    SAFEARRAY* psa = *( hoge.pparray ); // psa = hoge.parrayかも。VT_BYREFと関連しそう

    ::SafeArrayGetLBound( psa, 1, &lb );
    ::SafeArrayGetUBound( psa, 1, &ub );

    ::SafeArrayLock( psa );

    for ( long i = lb; i <= ub; i++ )
    {
        BSTR wcs;
        ::SafeArrayGetElement( psa, &i, ( void* )&wcs );
        ary.Add( CString( wcs ) );
    }

    ::SafeArrayUnlock( psa );
}


kty  2006-12-01 19:07:52  No: 63764

すみません。
自分でもまだよくわかっていませんので。。。

サンプルコードがあったのですが理解できないです。

// Data (応答データを取得)
  long nBufferLen = 0;
  PBYTE pBUffer = NULL;
  if (m_EditData.GetBufferData(pbyData, &nOffset, &nBufferLen, &pBUffer) == false) {
    ::GlobalUnlock(hGlobal);
    ::GlobalFree(hGlobal);
    return MAKELRESULT(0, 0);
  }

  // バイト配列を作成
  CComVariant vaData;
  SAFEARRAY *psaData = NULL;
  SAFEARRAYBOUND rgsabound[1];
  rgsabound[0].lLbound = 0;
  rgsabound[0].cElements = nBufferLen;
  psaData = ::SafeArrayCreate(VT_UI1, 1,  rgsabound);

  // データをコピーする
  PVOID pTargetData = NULL;
  HRESULT hr = ::SafeArrayAccessData(psaData, (void HUGEP**)&pTargetData);
  if (FAILED(hr)) {
    ::SafeArrayDestroy(psaData);
    delete pBUffer;        // バッファ開放
    ::GlobalUnlock(hGlobal);
    ::GlobalFree(hGlobal);
    return MAKELRESULT(0, 0);
  }

  memcpy(pTargetData, pBUffer, nBufferLen);
  ::SafeArrayUnaccessData(psaData);

  // そのデータをm_vaDataの中に格納する
  vaData.vt = VT_ARRAY | VT_UI1;
  vaData.parray = psaData;

  delete pBUffer;  // バッファ開放


Blue  2006-12-01 19:12:17  No: 63765

とりあえず、サンプルコードはどうでもよくて
結局何をしたいのか説明できますか?

>「解凍する」の説明がないのでどうしようもできませんけど。
の回答がつかないようであれば、私はおります。


kty  2006-12-01 19:30:51  No: 63766

圧縮されているデータ(VARIANT配列)を
解凍させたいだけ。


Blue  2006-12-01 19:38:05  No: 63767

シャノンさんもおっしゃっていますが、
どのように圧縮されていて、どのように解凍するのでしょうか?
(たとえば、ファイルの圧縮方法で、zipの解凍方法とlzhの解凍方法が異なるのと同じで、
どのように圧縮されているのか説明がないとどう解凍してよいのか誰にもわからない)


  2006-12-01 20:47:10  No: 63768

ktyさん、あなたは他人に
>圧縮されているデータを解凍させたいだけ。
とだけ言われて理解できますか?


kty  2006-12-02 00:06:10  No: 63769

すみません。
>どのように圧縮されていて、どのように解凍するのでしょうか?
COMを使って送受信されていますので、
元のデータがどのように圧縮されているかわかりません。

解凍方法はUncompressEx関数を使ってみたんですが、引数の型が合わなく苦戦しています。


シャノン  2006-12-02 08:26:51  No: 63770

> 元のデータがどのように圧縮されているかわかりません。

ならば結論はひとつです。
それがわからない限り、解凍できません。あきらめてください。

> 解凍方法はUncompressEx関数を使ってみたんですが、引数の型が合わなく苦戦しています。

それ、何の関数ですか?
どうも WMI にそんな関数があるみたいですが…


kty  2006-12-05 01:25:12  No: 63771

UncompressEx(解凍データ,解凍データ長,圧縮データ,圧縮データ長)
で解凍できると思うのですが、最初のパラメータの解凍データの領域を
作成するにはどうしたらよいのでしょうか?
BYTE型が入ります。

int CCompZLIB::UncompressEx (BYTE *dest,                              ULONG *destLen,
      const BYTE *source,    
                              ULONG sourceLen)
な感じで


PATIO  2006-12-05 01:43:15  No: 63772

CCompZLIB::UncompressExこの関数どっから出てきたんでしょう?
今までの話の流れに全く内容ですけれど、特にCCompZLIB::の部分。
問題のCOMを作った所から提供されていて、それで回答せよという指示が
あるのであれば、それで解凍してくださいとしか言いようが無いですよ。

他から提供されているライブラリを使っているのであれば、
そのライブラリの中身を理解する所からはじめて下さい。
貴方が理解していない物を掲示板を読んでいる人にわかるように
説明できるとはとても思えないです。
少なくともどういうものでどうすれば使えるのか程度は理解していないと
説明できないと思いますよ。
サンプルソースにしても理解していないのなら提示しても意味を成しませんし。


PATIO  2006-12-05 01:48:47  No: 63773

誤字だらけ。

誤)
今までの話の流れに全く内容ですけれど、特にCCompZLIB::の部分。

正)
今までの話の流れに全く無いようですけれど、特にCCompZLIB::の部分。

誤)
問題のCOMを作った所から提供されていて、それで回答せよという指示が

正)
問題のCOMを作った所から提供されていて、それで解凍せよという指示が

あと追記ですが、
サンプルソースと言っても前後の繋がりの部分が欠落しているようなので
その部分が無いと何とも判断できませんし、そもそも何を行う処理のサンプル
なのかも提示されていませんよね。
掲示板は文字でのやり取りになるので少なくとも質問する側が
文字で説明できる程度は理解していないと話が前に進みません。
この辺は御自分で努力していただくしか無いです。
あと、仕事で提供されているものなら提供元にサポートして貰うのが
本当だと思いますが、それは不可能なんでしょうか?


kty  2006-12-05 02:13:46  No: 63774

わかりました。
提供元に聞いてみます。
ご迷惑おかけしました。


Blue  2006-12-05 02:32:18  No: 63775

// 2006/12/01(金) 10:07:52
// のとおり Variant型変数に圧縮されたデータが格納されているという前提

if ( !( vaData.vt & ( VT_ARRAY | VT_UI1 ) ) )
{
    // エラー処理
    return 0; // 適当
}

SAFEARRAY* psa = vaData.parray;

// 長さの取得
LONG lb, ub;
::SafeArrayGetLBound( psa, 1, &lb );
::SafeArrayGetUBound( psa, 1, &ub );
ULONG nTargetLen = ub - lb + 1;

// データの取得
BYTE* pTargetData = NULL;
HRESULT hr = ::SafeArrayAccessData( psaData, ( void** )&pTargetData );
if ( FAILED(hr) )
{
    // エラー処理
    return 0; // 適当
}

// 解凍
// ※解凍されるとどれぐらいのサイズになるか不明なので XXXXX とします。
//   おそらく「ULONG *destLen」となっていることから、一度CCompZLIB::UncompressEx
//   の第一引数にNULLを指定して長さを取得するんだと思うけど。
ULONG destLen = XXXXX;
BYTE* dest = new BYTE[ destLen ];
int ret = CCompZLIB::UncompressEx( dest, destLen, pTargetData, nTargetLen );
// 戻り値によってなんかやる。
// ※戻り値が何なのか不明だからなにもかけん

// destが解凍されたデータ
// 使わなくなったら dest を deleteする
delete dest;


Blue  2006-12-05 02:33:23  No: 63776

::SafeArrayUnaccessData( psa );

が抜けました。
UncompressExの直後に入れておけばよいかと。


kty  2006-12-06 00:25:30  No: 63777

すみません。お願いします。

上記Blueさんのようにコードを書いてみたんですがコンパイルエラーになってしまいました。

error C2664: 'UncompressEx' : 2 番目の引数を 'unsigned long' から 'unsigned long *' に変換できません。 (新しい機能 ; ヘルプを参照)
整数型からポインタ型への変換には reinterpret_cast、C スタイル キャストまたは関数スタイル キャストが必要です。

となります。
宜しければ教えてください。


Blue  2006-12-06 00:30:12  No: 63778

&がついていなかったです。
>int ret = CCompZLIB::UncompressEx( dest, destLen, pTargetData, nTargetLen );
int ret = CCompZLIB::UncompressEx( dest, &destLen, pTargetData, nTargetLen );

それと、
>// ※解凍されるとどれぐらいのサイズになるか不明なので XXXXX とします。
>//   おそらく「ULONG *destLen」となっていることから、一度CCompZLIB::UncompressEx
>//   の第一引数にNULLを指定して長さを取得するんだと思うけど。
と書いたように、XXXXXをどのように取得するか明確にしないと、適当適当では
絶対不味いでしょう。

あと

>delete dest;

delete[] dest;

でした。


kty  2006-12-06 00:39:31  No: 63779

ありがとうございます。

>// ※解凍されるとどれぐらいのサイズになるか不明なので XXXXX とします。
ですが、1M以下になると思われています。

コンパイルしたら
error C2352: 'CCompZLIB::UncompressEx' : 静的でないメンバ関数の中で呼び出しが正しくありません。
'UncompressEx' の宣言を確認してください。

と表示されました。
今試行錯誤していますが。。。


Blue  2006-12-06 00:53:55  No: 63780

>コンパイルしたら
>error C2352: 'CCompZLIB::UncompressEx' : 静的でないメンバ関数の中で呼び出しが正しくありません。
>'UncompressEx' の宣言を確認してください。
これは、私ではどうにも出来ません。
(というか、CCompZLIB::UncompressExにかんしてなにも情報がないので
この掲示板を見ている人のだれもが解凍できないでしょう)

エラーメッセージの「静的でないメンバ関数」というのから、
インスタンスが必要になるメソッドなんでしょう。
つまり

CCompZLIB::UncompressEx

のような使い方ではなく

CCompZLIB hoge; // コンストラクタが不明なので間違っている可能性がある



hoge.UncompressEx(、、、、、

てな使い方になるでしょう。

結局のところ
>提供元に聞いてみます。
をやってもらわないとこちらもさっぱりです。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加