C++でVB用にポインタをラップするようなクラスを作ろうと思っています。
VBからByRefで変数を受け取って、そのポインタを保持し、
そのポインタの参照先の変数の値を取得したり、代入するメソッドを実装します。
しかし、ポインタを受け取る時点で、正しいポインタが受け取れていないようです。
idlファイルはおよそウィザードに任せていますが、扱うのは初めてなので、
ドのようにすればByRefで正しいポインタを受け取れるのか教えていただけないでしょうか。
---------------------------------------------
VbHelpLibrary.idl
...
interface ILongRef : IDispatch{
[propget, id(1), helpstring("プロパティ Ptr")] HRESULT Ptr([out, retval] long *pVal);
[propput, id(1), helpstring("プロパティ Ptr")] HRESULT Ptr([in] long* newVal);
[propget, id(2), helpstring("プロパティ Value")] HRESULT Value([out, retval] long *pVal);
[propput, id(2), helpstring("プロパティ Value")] HRESULT Value([in] long newVal);
};
---------------------------------------------
LongRef.cpp
STDMETHODIMP CLongRef::get_Ptr(long *pVal){
*pVal = (long)this->m_ptr;
return S_OK;
}
STDMETHODIMP CLongRef::put_Ptr(long *newVal){
this->m_ptr = newVal; //ここでnewValがVarPtr(X)と一致しない
//*newVal = 100; //試しにここでこのポインタの先に値を入れてもXは変化しない
return S_OK;
}
STDMETHODIMP CLongRef::get_Value(long *pVal){
*pVal = *m_ptr;
return S_OK;
}
STDMETHODIMP CLongRef::put_Value(long newVal){
*m_ptr = newVal;
return S_OK;
}
---------------------------------------------
Module1.bas
Sub Main()
Dim X As Long, Y As New LongRef
Debug.Print "VarPtr(X) = ", VarPtr(X)
Y.Ptr = X
Debug.Print "Y.Ptr = ", Y.Ptr
---------------------------------------------
結果
VarPtr(X) = 1308376
Y.Ptr = 1929464
No.2ベストアンサー
- 回答日時:
>>STDMETHODIMP CLongRef::get_Ptr(long *pVal)
>としたのは、long**にするとVBで扱えなくなってしまったからです。
なるほど、試してみましたが確かに VB ではエラーになってしまいました。
プロパティとして考えると違和感がありますが、これはこれで仕方がないかなと思います。
>[id(3), helpstring("メソッド setPtr")] HRESULT setPtr([in] long* newVal);
>を作ってみたのですが、結果が同じでした。
私も試してみましたが、意図したものになりましたよ。
.idl
==================================================================================
[propget, id(1), helpstring("プロパティ Ptr")] HRESULT Ptr([out, retval] long * pVal);
[id(3), helpstring("メソッド SetPtr")] HRESULT SetPtr(long * newVal);
.cpp
==================================================================================
STDMETHODIMP CLongRef::get_Ptr(long * pVal)
{
*pVal = (long)m_ptr;
return S_OK;
}
STDMETHODIMP CLongRef::SetPtr(long * newVal)
{
m_ptr = newVal;
return S_OK;
}
VB
==================================================================================
Dim X As Long
Dim Y As New LongRef
X = 100
Debug.Print "VarPtr(X) = " & VarPtr(X)
'Y.Ptr = X
Y.SetPtr X
Debug.Print "Y.Ptr = " & Y.Ptr
実行結果
==================================================================================
VarPtr(X) = 1306696
Y.Ptr = 1306696
STDMETHODIMP CLongRef::SetPtr(long * newVal)
の中身はどのようになってますか?
>idlとcppとhだけだと思っていたのですが、他にも対にしなければならないものがありますか?
.idl、.cpp、.h だけで良いと思います。
遅くなってすみません。
>私も試してみましたが、意図したものになりましたよ
もういちどクラスからウィザードで作り直したら、意図した結果になりました。
やはり、クラスウィザードが管理している触ってはいけない部分を、いつの間にか変えてしまっていたのかもしれません。
また、Long変数をputしてlong*の値をgetするのも変なので、Ptrプロパティは単にm_ptrをLongとしてラップするプロパティとして、SetPtrを別に設けることにします。
ありがとうございました。
No.1
- 回答日時:
VB では Integer や Long 等の値型の変数に対して
Z = X
のようにすると値渡しで代入されます。これは代入先がプロパティの場合でも同じです。
つまり、
Y.Ptr = X
とすると、VB 側で X のコピーが作られ、X のコピーが Y.Ptr に渡されます。
STDMETHODIMP CLongRef::put_Ptr(long *newVal)
の newVal は [ X のコピーのアドレス] になります。
VB の言語仕様として Integer や Long の参照型変数というものがない以上、プロパティで参照渡しはできないでしょう。
なので、プロパティでなく関数にしなければならないと思います。(いうまでもなく、引数は参照渡しにしなければなりません。)
実行結果が
>VarPtr(X) = 1308376
>Y.Ptr = 1929464
のように、値が大きく異なっているのは、
STDMETHODIMP CLongRef::get_Ptr(long **pVal)
とすべきところが
STDMETHODIMP CLongRef::get_Ptr(long *pVal)
となっているためではないかと思います。
( ただしいコピーのアドレスであれば、もっと近い値になるのあ普通だと思います。)
ちなみに、VB は 6.0 ですか?
この回答への補足
解凍ありがとうございます。
すいません、バージョンを書いていませんでした。
VBもVC++も6.0です。
>STDMETHODIMP CLongRef::get_Ptr(long *pVal)
としたのは、long**にするとVBで扱えなくなってしまったからです。
>VB の言語仕様として Integer や Long の参照型変数というものがない以上、プロパティで参照渡しはできないでしょう
VBで書いたら以下のようになることを、C++で書こうと思いました。
Property Get Ptr() As Long
Ptr = m_ptr
End Property
Property Let Ptr(ByRef RHS As Long)
m_ptr = VarPtr(RHS)
End Property
上記のコードではLetで実際に渡るのはLongポインタで、Getで返すのはLong値だとおもいます。
このため、long *pValとしましたが、イレギュラーでしょうか・・・?
ためしに、
[id(3), helpstring("メソッド setPtr")] HRESULT setPtr([in] long* newVal);
を作ってみたのですが、結果が同じでした。
ためしに、別のクラスVariantRefを作って同じようなことをやってみたのですが、
[id(3), helpstring("メソッド setPtr")] HRESULT setPtr([in] VARIANT* newVal);
は、ちゃんと正しいなポインタを受取れました。
あとから作ったVariantRefはプロパティとメソッドの作成をすべてウィザードに任せたのですが、LongRefでは試行錯誤しながらだったので、メンバを作ったり消したり、型を変えたりしてしまったのが行かなかったのでしょうか?
ウィザードがメンバの作成時に追記したのは、質問のところで書いた、idlとcppとhだけだと思っていたのですが、他にも対にしなければならないものがありますか?
VBでクラスを作ったり、C++で普通のクラスを作ったりはしているのですが、C++でATLクラスを作るのは初めてなうえ、文献もあまり見つからないため、ご教授いただきたいと思っております。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) VBAでのMATCH関数 3 2022/10/17 19:06
- Visual Basic(VBA) 別シートのデータを参照して値を入れたい。 まとめデータシートのC列D列の値を商品一覧シートのコードが 7 2022/08/17 13:20
- Visual Basic(VBA) いつもお世話になっております、VBAで教えて頂きたいのですが 2 2022/05/05 22:20
- Visual Basic(VBA) 稀に1円合いません? Sheet1から金額と個数を貼り付ける下記コードで、金額を切り上げるコードを何 3 2022/09/05 15:11
- Visual Basic(VBA) VBAで時間(00:00形式)を積算(足し算)したい 1 2022/11/15 17:04
- Visual Basic(VBA) VBAで質問ですが、皆さんはどの様に導き出しているのでしょうか? 6 2022/05/03 21:53
- Excel(エクセル) VBAの指示の内容 昨日こちらでご教示頂いたのですが初心者な為、一つ一つの指示が何をやっているのかわ 2 2022/10/25 18:08
- Visual Basic(VBA) vbaを早くしたい 5 2022/09/09 10:58
- Visual Basic(VBA) VBA処理追加 こちらでご教示頂いたのですが回答完了させてしまいましたのでこちらからまた質問させてく 2 2022/10/27 09:57
- Visual Basic(VBA) 別シートから年齢別の件数をカウントしたいの続き 5 2023/01/24 00:16
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語のサフィックスについて
-
初期化関数でmallocしたい
-
他のフォームから別のフォーム...
-
エクセルVBAでテキストボッ...
-
【VB6.0】 あるフォームから他...
-
perlによるxmlファイルの取得
-
タイムアウトする仕組みを作りたい
-
C#のループでtextboxに値を入れ...
-
sublimit textっていうエディタ...
-
三項でたとえば交換って
-
VS CodeでTEXファイルにPDF形式...
-
pthread_cond_waitとptherad_co...
-
二点の座標から距離や角度を求...
-
【VB.NET】テキストボックスに...
-
VB.NETでのイベントの途中終了
-
VB6のFriendについて
-
verilogのcase文
-
アクセスできない保護レベルエ...
-
【VBS】クリップボード操作につ...
-
レコードセットにnullの場合
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語のサフィックスについて
-
「ずっと憧れていました」は英...
-
初期化関数でmallocしたい
-
変数の型でlong longとunsigned...
-
1) A uniform ladder 10.0 m lo...
-
三項でたとえば交換って
-
VBA public変数はどのようなこ...
-
C#のループでtextboxに値を入れ...
-
VBAでcallで呼び出したsubを終...
-
他のフォームから別のフォーム...
-
レコードセットにnullの場合
-
エクセルVBAでテキストボッ...
-
Functionの戻り値を配列にした...
-
プログラムの素朴な質問です 分...
-
VB.NETでのイベントの途中終了
-
sublimit textっていうエディタ...
-
アクセスできない保護レベルエ...
-
チェックボックスを操作できな...
-
String型の値にスラッシュをつ...
-
Excel VBAでsub,dimは何の略?
おすすめ情報