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

A 回答 (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 だけで良いと思います。
    • good
    • 0
この回答へのお礼

遅くなってすみません。

>私も試してみましたが、意図したものになりましたよ
もういちどクラスからウィザードで作り直したら、意図した結果になりました。
やはり、クラスウィザードが管理している触ってはいけない部分を、いつの間にか変えてしまっていたのかもしれません。

また、Long変数をputしてlong*の値をgetするのも変なので、Ptrプロパティは単にm_ptrをLongとしてラップするプロパティとして、SetPtrを別に設けることにします。

ありがとうございました。

お礼日時:2011/05/03 19:37

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クラスを作るのは初めてなうえ、文献もあまり見つからないため、ご教授いただきたいと思っております。

補足日時:2011/04/30 19:36
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QVB6(SP5)とSTARFAXのOCX

こんにちは。宮本と申します。VB6(SP5)でプログラミングをしております。
STARFAXのOCXを使用して直接FAXに送りたいのですが、
サポートがHPでしかしておらず、非常に不安なのです。
そこで、書籍等、教えて頂きたいのです。
よろしくお願い致します。

Aベストアンサー

Microsoft FaxがインストールされたマシンにFax COM(faxcom.dll)というコンポーネントが含まれているのであれば、COMで送付先の番号などを指定して送信することができるはずなのですが。たとえば、
dim fdoc as faxdoc
with fdoc
.faxnumber="XXXX"
.filename="c:\sample.txt"
.send
end with
みたいなことができるみたいです。
うちのマシンはちょっと特殊なので(SBSの共有FAXサービスを使ってます)ふつうのマシンにはこのコンポーネントがないかもしれません。

QC++BuilderやDelphiでVC++用のDLLの作成

C++Builderの画面から新規作成からDLLウィザードを選ぶと、VC++スタイルのDLLを選択して作成できるようになっています。VC++用のDLLを作成出来るとは書かれていません。実際、VC++コンパイラからリンクを拒否されます。

また、VC++用のインポートライブラリをCOFF形式からBorland用のOMF形式に変換するユーティリティCOFF2OMF)は存在していますが、OMF形式をCOFF形式に変換する手法を見かけません。

変換方法を書いているWEBや雑誌記事とかを紹介してください。

Aベストアンサー

C++BuilderのDLLウィザードでの「VC++スタイル」はヘルプにあるようにエントリポイントが DLLMain になるだけです。
DLLはC++Builderで作成してもVisualC++で作成しても、どちらからも利用することができます。
MFC拡張など利用する側に対応が必要なDLLは別ですが。

C++BuilderとVisualC++ではインポートライブラリに互換性がありません。
C++Builder の場合は付属のツール implib.exe でDLLからインポートライブラリを生成できますが、VisualC++では簡単な方法はありません。

VisualC++での正攻法は LIB.EXE を使ってインポートライブラリを作成することですが、DEFファイルを書いてやらないといけません。
http://bme.t.u-tokyo.ac.jp/members/manabu/MKL_BCC/mkl_BCC.html
のdllからふるいCOFF形式のlibを作成するのところ。
http://www.sun-inet.or.jp/~yaneurao/dlang/Chapter-05.html#050800000000
がもう少し分かりやすいかもしれません。

私の場合は LoadLibrary(), GetProcAddress() で動的に呼び出すか、同じ定義の関数をエクスポートするダミーのDLLを作ってインポートライブラリを得ます。

参考URL:http://www.sun-inet.or.jp/~yaneurao/dlang/Chapter-05.html#050800000000

C++BuilderのDLLウィザードでの「VC++スタイル」はヘルプにあるようにエントリポイントが DLLMain になるだけです。
DLLはC++Builderで作成してもVisualC++で作成しても、どちらからも利用することができます。
MFC拡張など利用する側に対応が必要なDLLは別ですが。

C++BuilderとVisualC++ではインポートライブラリに互換性がありません。
C++Builder の場合は付属のツール implib.exe でDLLからインポートライブラリを生成できますが、VisualC++では簡単な方法はありません。

VisualC++での正攻法は LIB...続きを読む

QVB6で作成したOCX(ActiveX)について

お世話になります。
下記項目に対しての知識が無くて困っております。

VB6.0で作成したOCX(ActiveX)についてですが、VC++やVB以外のプログラム言語で使用できるのでしょうか?
今回はDelphiでの使用を検討しておりますが、環境が無い為試すことができません。

ご存知の方がいたら、ご教授お願いいたします。

Aベストアンサー

DelphiはActiveXを利用するためのインターフェイスを持っています。

メニューの、「コンポーネント」→「ActiveX コントロールの取り込み」を使うと、通常のVCLコンポーネントのように使えます。
VBとはメソッドやプロパティの呼び出し方が若干違ったりするところもありますので戸惑うかもしれませんが、ほとんどの場合、取り込んだActiveXの全ての機能を利用できます。

参考URLをどうぞ

参考URL:http://www.wakhok.ac.jp/~tetsuo/delphi/text/chap_a/pb_a03.html

QC,C++,C++/CLIの構造体とクラス

C++の構造体・クラスって、メンバのアクセス指定子のデフォルトが
privateかpublicかという違い「だけ」しか全くないのでしょうか?

クラスにおける
value class / ref class
という分類はC++/CLIのもので
これについては
value class の方は C言語の構造体に近いという事でいいでしょうか?

ref classの方は
ネイティブのC++のクラスを
マネージ用にしたようなもので

C++/CLIの構造体は
C++のそれと同じで
OKですか?

そしてそれらの構造体には、値型・参照型といった分類はないのでしょうか?

Aベストアンサー

> ということは、structも継承可、という事でしょうか?

structでも継承可能です。

> 継承のアクセス指定の方は
> クラスと構造体ではどうなるのでしょうか?

class A : Base {};



class A : private Base {};

と等価です。
一方、

struct A : Base {};



struct A : public Base {};

と等価です。

> そして「集成体」というのが初めて知ったのですが
> これはいわゆる、配列や・・・ある条件下でのクラス・・?
> なのでしょうか?

配列と以下の条件をすべて満たすクラスのことです。
・ユーザー定義のコンストラクタを持たない
・非公開または限定公開のメンバを持たない
・基底クラスを持たない
・仮想関数を持たない

ちなみにC言語の集成体は、配列と構造体の総称です(共用体は集成体ではありません)。

QVB6のランタイム

いろんなHPで、VB6のランタイムをダウンロードして、
セットアップしたのですが、正しく動作しないのですが

全ての機能(DLL・OCX等)があるHPはないのですか?
もしなけらば作成方法を教えてください。

VB6のCDにありますか?

Aベストアンサー

VB6をセットアップしてSP5を充てれば動作すると思いますよ。
でも起動しようとしているアプリケーションに、
インストーラーは付いていなかったのでしょうか?

以下のHPにないような特別なランタイム(OCX)を使用しているのであれば、
インストーラーに付加していない開発者の怠慢ですね。

それとも製品として販売されているOCXが必要なんて事は無いですか?

参考URL:http://www.vector.co.jp/vpack/filearea/win/util/runtime/index.html

QC++/CLIで、アンマネージC++のDLLを使用する方法

こんにちは。
C++/CLIのプログラムで、アンマネージC++のDLLを使用したいと考えています。
ネット上をいろいろ調べたのですが、具体的な手段がわかりません。
見よう見まねで以下のようにサンプルを作成したのですが、コンパイルすら通る状況になりません。
かなり基本的な問題がありそうで申し訳ないのですが、下記の問題点を教えていただけないでしょうか。

また、参考になりそうなサイトなどありましたら教えていただけると大変助かります。

■アンマネージC++のDLL
VC++6.0で、以下のように、単にデバッグ文字列を書き出すだけのDLL関数を作成しました。
(このDLLが使用できることは他のVC++6.0プロジェクトで確認済みです)
/*-----Func.h-----*/
#ifndef __FUNC_H__
#define __FUNC_H__

AFX_EXT_CLASS void WINAPI ShowMessage();

#endif//__FUNC_H__

/*-----Func.cpp-----*/
#include "StdAfx.h"
#include "Func.h"
#include <stdio.h>

void WINAPI ShowMessage()
{
CString str = "This is The Message from DLL Func!\n";
OutputDebugString(str);
}

■C++/CLI でのDLL使用
Visual Studio2008にて、C++のCLRプロジェクトを作成して、以下のようにDLLを使用する準備を行いました。
1.ソリューションエクスプローラのヘッダフォルダに、Func.hを追加
2.プロジェクトのフォルダに、上記で作成したFuncのDLLとLIBファイルを置く。
3.プロジェクトの「プロパティ > C/C++ > プリプロセッサ > プリプロセッサの定義」に、"_AFXDLL"を追加
4.mainクラスのソースに以下を記述
/*----------*/
using namespace System;
#include "Func.h"
#using "ManagedDllApp.dll"

int main()
{
ShowMessage();
return 0;
}
/*----------*/

この状態でコンパイルすると、
「エラー3error C2144: 構文エラー : 'void' は ';' によって先行されなければなりません。d:\xxx\Func.h4Console
」等、Func.h周りで複数のエラーが出ます。
また、Func.hをインポートしないでコンパイルすると、
「エラー3fatal error C1113: #using が 'd:\xxx\manageddllapp.dll' で失敗しました。」と、Dllでエラーが出ます。

よろしくお願いいたします。

こんにちは。
C++/CLIのプログラムで、アンマネージC++のDLLを使用したいと考えています。
ネット上をいろいろ調べたのですが、具体的な手段がわかりません。
見よう見まねで以下のようにサンプルを作成したのですが、コンパイルすら通る状況になりません。
かなり基本的な問題がありそうで申し訳ないのですが、下記の問題点を教えていただけないでしょうか。

また、参考になりそうなサイトなどありましたら教えていただけると大変助かります。

■アンマネージC++のDLL
VC++6.0で、以下のように、単にデ...続きを読む

Aベストアンサー

 こんばんは。御礼頂きました。
 Func.hの中にインクルードし忘れがある様です。準備が出来たら、必ず「ソリューションのリビルド」をして下さい。
 以下は DLL->VC6.0Pro CLR->VC2005Pro で確認しています。

/*-----Func.h-----*/
#ifndef __FUNC_H__
#define __FUNC_H__

#include"afxver_.h"//此れと
#include"afxv_dll.h"//此れと
#include<windows.h>//此れをインクルード

AFX_EXT_CLASS void WINAPI ShowMessage();

#endif //__FUNC_H__

//以下はCLRアプリ側

/*-----stdafx.h-----*/
// stdafx.h : 標準のシステム インクルード ファイルのインクルード ファイル、または
// 参照回数が多く、かつあまり変更されない、プロジェクト専用のインクルード ファイル
// を記述します。
//
#pragma once

// TODO: プログラムに必要な追加ヘッダーをここで参照してください。
#include"func.h"
#pragma comment(lib, "libの名前.lib")

/*-----clrconsole.cpp-----*/
// clrconsole.cpp : メイン プロジェクト ファイルです。

#include "stdafx.h"

using namespace System;

int main(array<System::String ^> ^args)
{
::ShowMessage();
return 0;
}

 こんばんは。御礼頂きました。
 Func.hの中にインクルードし忘れがある様です。準備が出来たら、必ず「ソリューションのリビルド」をして下さい。
 以下は DLL->VC6.0Pro CLR->VC2005Pro で確認しています。

/*-----Func.h-----*/
#ifndef __FUNC_H__
#define __FUNC_H__

#include"afxver_.h"//此れと
#include"afxv_dll.h"//此れと
#include<windows.h>//此れをインクルード

AFX_EXT_CLASS void WINAPI ShowMessage();

#endif //__FUNC_H__

//以下はCLRアプリ側

/*-----stdafx.h-...続きを読む

Qtxt2assとvb6ランタイム

txt2assというフリーソフトを起動するために
vb6ランタイムとDirectX9.0が必要ということで
ダウンロードしたのですが

コンポーネントtabctl32.ocxまたはその依存関係のひとつが
適切に登録されていません。ファイルが存在しないか不正です。

というエラーが出て起動できません。
vb6がちゃんと入っていないのかと思い
何度か試したのですが同じ結果になります。

Vistaを使っていますが
ソフトのヘルプ画面にはVistaでも作動可能と書いてありました。
原因がわかる方いらっしゃいましたら
よろしくお願いします。

Aベストアンサー

以下で配布されているVB6ランタイムは、tabctl32.ocxが
含まれています。
違う物をインストールしたのでしたら、こちらをどうぞ。
http://www.hmpage.jp/vb6rtest.htm

QDLL VBとC++

VBAからVC++2005のDLLを呼び出すプログラムを書いています。

VB側で作成したcpp_proc関数を呼ぶとVBアプリ自体が落ちました。

DLLのreturnの直前に以下のMessageBoxで表示させるとそこまでは表示され、
リターンを押すと、落ちました。

VB側の引数の値 String * 8192が悪いのでしょうか?
return直前まで動作していたので、DLLの戻り値に何か原因があるのでしょうか?


ついでの質問ですが、DEFの @1は無くても動くのでしょうか?
意味が知りたいです。


// ----- C++ (DLL側) -----

int __stdcall cpp_proc(LPCSTR inp, LPSTR out)
{

... 省略

MessageBox(0, "ここまで通過", "debug", MB_OK);

return 0;

}


// ----- DEF -----

LIBRARY "example"
DESCRIPTION 'テスト'

EXPORTS
; 明示的なエクスポートはここへ記述できます
cpp_proc @1


'----- VB側 -----

Public Declare Function cpp_proc Lib "example.dll" _
(ByVal inp As String, ByRef out As String) As Integer

Public Sub Test()
Dim ret As Integer
Dim inp As String
Dim out As String * 8192

ret = cpp_proc(inp, out)

MsgBox("ret=[" & Cstr(ret) & "]");

End Sub

VBAからVC++2005のDLLを呼び出すプログラムを書いています。

VB側で作成したcpp_proc関数を呼ぶとVBアプリ自体が落ちました。

DLLのreturnの直前に以下のMessageBoxで表示させるとそこまでは表示され、
リターンを押すと、落ちました。

VB側の引数の値 String * 8192が悪いのでしょうか?
return直前まで動作していたので、DLLの戻り値に何か原因があるのでしょうか?


ついでの質問ですが、DEFの @1は無くても動くのでしょうか?
意味が知りたいです。


// ----- C++ (DLL側) -----

int ...続きを読む

Aベストアンサー

 こんにちは。補足頂きました。確かに可笑しいです。
 SysAllocStringByteLen()を使用してVBに送り返すそうです。此れでは駄目でしょうか。

//
//VC側
//
#include"exsample.h"
#include<string.h>
#include<comutil.h>
#pragma comment(lib, "comsupp.lib")
#pragma comment(lib, "comsuppw.lib")

int __stdcall cpp_proc(LPSTR inp, BSTR* out)
{
CHAR buf[1024];
strcpy(buf, inp);
MessageBoxA(0, buf, "化け文字??", MB_OK); // 文字化け? わかりません?

// ついでに、outに "結果はゼロです" という日本語文字を返したいです。
// どう書けばよいか、わかりません。
SysFreeString(*out);
LPCSTR psz = "結果はゼロです";
*out = SysAllocStringByteLen(psz, ::strlen(psz));

// 戻り値
return 2;
}

//
//VB側
//
Public Declare Function cpp_proc Lib "tovba.dll" (ByVal inp As String, ByRef out As String) As Integer


Public Sub Test()

Dim ret As Integer
Dim inp As String
Dim out As String

inp = "abcdefg"
'out = Space(1024) 必要なし

ret = cpp_proc(inp, out)

MsgBox ("ret=[" & CStr(ret) & "]") '2が返ります。
MsgBox ("inp=[" & inp & "]") '送った内容 abcdefg
MsgBox ("out=[" & out & "]") '「結果はゼロです」という文字を表示させたい。
MsgBox ("outLength=[" & CStr(Len(out)) & "]") '文字数の計測

End Sub

 こんにちは。補足頂きました。確かに可笑しいです。
 SysAllocStringByteLen()を使用してVBに送り返すそうです。此れでは駄目でしょうか。

//
//VC側
//
#include"exsample.h"
#include<string.h>
#include<comutil.h>
#pragma comment(lib, "comsupp.lib")
#pragma comment(lib, "comsuppw.lib")

int __stdcall cpp_proc(LPSTR inp, BSTR* out)
{
CHAR buf[1024];
strcpy(buf, inp);
MessageBoxA(0, buf, "化け文字??", MB_OK); // 文字化け? わかりません?

// ついでに、outに "結...続きを読む

QVB6のアプリケーションの配布

VB6でアプリケーションを作成したのですが、他のマシンに配布する場合に実行形式(EXE)だけだと、DLLやOCXなどの有無やバージョンの違いで動作しないのですが、Setup.exeなどダブルクリックするだけで、インストールできるようにしたいですが、方法がわかりません。
VBのランタイムは、このSetup.exeより先にインストールしないと、Setup.exe自体でインストールが中断されるのでしょうか?

あと、.NETですがVB6のようにDLLやOCXの有無・バージョン違いなど気にせず簡単に配布できるのがメリットの一つと解釈しても良いのでしょうか?

このように配布・インストール関連で詳しい書籍などご存知でしたら教えてください。
インストーラソフトというものは言葉聞いたことがあるのですが、
.NET使うならば、あまり必要ないのでしょうか?これもお勧めのインストーラソフトがあるのでしたらご教授下さい。

Aベストアンサー

殆どのVB製フリーソフトでは別途ランタイムをインストールしてくださいで済ましているようですが。
どうしても組み込みたいということでしたら、インストーラーの作成時に組み込みましょう。殆どの人はそれで問題がおきる(低バージョンのDLLでの上書きとか)ことが予想されるため、ユーザー任せにしているわけで。
>Setup.exe自体でインストールが中断
そのインストーラー自体が特定のDLLやOCXに依存して作っているのなら先に必要となりますが、殆どのケースでは必要ないように作られるかと思います。どうやって作ったのか次第です。

.NETの場合は、これらのVB時代の反省を生かして所謂ランタイム的なものを.NetFrameWorkとしてマイクロソフトが一元管理しています。そのため.NdetFrameWorkのバージョンが1.1なり2.0を入れておいて下さいとするだけで(またそのインストールがWindowsUPDATEから可能)特に作成者側が気を回す必要はなくなりました。

VB時代も含めてのインストーラーの参考URL
http://dobon.net/vb/installer/index.html

殆どのVB製フリーソフトでは別途ランタイムをインストールしてくださいで済ましているようですが。
どうしても組み込みたいということでしたら、インストーラーの作成時に組み込みましょう。殆どの人はそれで問題がおきる(低バージョンのDLLでの上書きとか)ことが予想されるため、ユーザー任せにしているわけで。
>Setup.exe自体でインストールが中断
そのインストーラー自体が特定のDLLやOCXに依存して作っているのなら先に必要となりますが、殆どのケースでは必要ないように作られるかと思います。どうやっ...続きを読む

QC++のクラスポインタの初期化?

C言語しか経験がないものです。最近Irrlichtでゲームをつくりはじめました。いきなりチュートリアルがわからないので質問させていただきます。

IrrlichtDevice *device =
createDevice( video::EDT_SOFTWARE, dimension2d<u32>(640, 480), 16,
    false, false, false, 0);

if (!device)
return 1;

という部分で、
(1) *devide = createDevice( ...);
 なぜクラスポインタが関数で初期化できるのですか。
 アドレスを入れないのはなぜなのでしょうか。

(2) if(!device)
 これだとアドレス値の式を判別しているように思いますが、どういうことですか。

初歩的な質問で申し訳ございません。

Aベストアンサー

若干語弊があるのですが。
C++のクラス、というのは、Cの構造体を拡張したものと考えてください。

> (1) *devide = createDevice( ...);

createDeviceの宣言を見てないのですが、IrrlichtDevice へのポインタを返す関数になってませんか?
Cでも
struct A * foo(~)
とかいう風に構造体(struct A)へのポインタを返す関数ってありますよね?

> (2) if(!device)
ポインタは NULL なら 「偽」、そうでないなら「真」です。
!は論理値の真偽を反転させます。
これはCでもよく使われる記法です。

例)
FILE *fp = fopen(~);
if (!fp){ /* → fp == NULL と同義 */
エラー;
}

> device だけならアドレスで、*device だとさしているオブジェクトそのものをあらわすと入門書には書いてある

それは「IrrlichtDevice クラスへのポインタ」と宣言されているからです。
宣言(+初期化)と、それ以外での使い方が違うのはCも同じです。

struct A * a; は struct Aへのポインタ aの宣言
それ以降のプログラム中では
a は struct Aへのポインタ
*a は aの実体(=strcut Aそのもの)

struct A b; では struct Aの変数 bの宣言
それ以降のプログラム中では
b は struct A型の実体
*b は bがポインタでは無いのでエラー


もし、Cの構造体やポインタについての理解が不十分なら、一度復習することをお勧めします。

若干語弊があるのですが。
C++のクラス、というのは、Cの構造体を拡張したものと考えてください。

> (1) *devide = createDevice( ...);

createDeviceの宣言を見てないのですが、IrrlichtDevice へのポインタを返す関数になってませんか?
Cでも
struct A * foo(~)
とかいう風に構造体(struct A)へのポインタを返す関数ってありますよね?

> (2) if(!device)
ポインタは NULL なら 「偽」、そうでないなら「真」です。
!は論理値の真偽を反転させます。
これはCでもよく使われる記法です。

例)
FILE *fp = fope...続きを読む


人気Q&Aランキング

おすすめ情報