C++/CLI Vector3D型で定義したメンバー変数がValueTypeと認識される

huahi11115 355 評価のポイント
2024-10-11T15:22:38.09+00:00

Microsoft Visual Studio Community 2022 (64 ビット) - Current Version 17.11.2

.Net Framework 4.8.1

C++/CLIでマネージド型のdllを作成し、VB.netから参照しています。

<C++/CLI>

public ref class TestClass {
public:
	System::Windows::Media::Media3D::Vector3D^ Vector3D_1 = gcnew System::Windows::Media::Media3D::Vector3D(1, 2, 3);
	float p1(){ // VB.net から、こういうやり方はしたくない
		return Vector3D_1->X;
	}
};

上のクラスをVB.netで使用すると、

<VB.net>

      'この様な処理を行いたい
        Dim v1 As New System.Windows.Media.Media3D.Vector3D(1, 2, 3)
        Dim v1x = v1.X 'これは動作する
        '異常動作
        Dim cl1 As New TestClass
        '↓varの型がSystem::Windows::Media::Media3D::Vector3D なのに、ValueTypeとなってしまう異常動作
        Dim var = cl1.Vector3D_1
        '↓varの型がVector3Dでないため、下の行のコンパイルが通らない
        'Dim x1 = var.x

cl1.Vector3D_1は、Vector3Dで定義されているのにValueTypeとなっています。

このため、cl1.Vector3D_1.x という参照方法が使えません。

なぜVector3D型と認識されないのですか。

.NET
.NET
.NET ソフトウェア フレームワークに基づく Microsoft テクノロジ。
74 件の質問
C++
C++
C プログラミング言語の拡張機能として作成された高レベルの汎用プログラミング言語。低レベルのメモリ操作機能に加えて、オブジェクト指向、汎用、関数型の機能を備えています。
24 件の質問
VB
VB
.NET Framework 上に実装される、Microsoft によって開発されたオブジェクト指向プログラミング言語。 旧称 Visual Basic .NET。
11 件の質問
{count} 件の投票

承認済みの回答
  1. gekka 10,561 評価のポイント MVP
    2024-10-12T11:17:02.3266667+00:00

    .NETのマネージ型にはobject型を基底とした値型と参照型しかありません。

    対してC++/CLIは追跡参照(%)オブジェクト参照ハンドル(^)があります。(と素のC++の値とポインタ*と参照&)

    VBにアドレスポインタを表現する方法がないように、.NETにはC++/CLIの値型に対するオブジェクト参照ハンドル(^)を表現する方法がありません。(参照型に対する参照ハンドルは.NETの参照型として公開されるので扱える)

    # C++でポインタ型(*)をフィールドで公開した場合、C#ではunsafeでそのフィールドを扱えるけどVBでは扱えないのと同じように機能がないので不可能
    # VBには値型の参照として関数の引数のByRefがあるけど、これはC++/CLIからみれば追跡参照%なのでハンドルではない
    # C#7のrefも追跡参照と同等

    よって値型のVector3Dに対するハンドルであるVector3D^をVBやC#でそのまま扱うことはできません。
    扱えないのは困るので、.NETの値型の基底であるValueTypeにボックス化することで公開できるようにされています。 ボックス化されているので、Vector3Dにキャストしてボックス化を解除ですればVector3Dとして取り出せます。(ただし値型のボックス化解除でコピーが発生するのでValue3D型のメンバの値だけを変更することはできません。)

    結論としてハンドルは扱えないので、クラスにVector3Dを参照ハンドルではないフィールドで定義すればNETにはそのまま元のVector3Dとして公開されます。

    1 人がこの回答が役に立ったと思いました。

1 件の追加の回答

並べ替え方法: 最も役に立つ
  1. Azulean 165 評価のポイント
    2024-10-12T16:43:01.4166667+00:00

    根本部分に何か誤解があるのでしょう。

    .Net Frameworkで定義されているSystem::Windows::Media::Media3D::Vector3Dがマネージド型かアンマネージド型かを区別する方法がわかりませんので教えて下さい。

    • .NET Frameworkに定義されている方はすべて「マネージ型」です。
      • 「マネージ」と「アンマネージ(またはネイティブ)」という対比の場合、「.NET Frameworkによって管理される型か否かの呼び分け」に過ぎません。
    • もしかすると、.NET Framework内の「値型」「参照型」の呼び分けと混同されているかもしれません。
      • C++/CLIにおいて「^」をつけるのは「参照型」であり、「Vector3D」は「値型」ですので通常「^」をつけません。

お客様の回答

回答は、質問作成者が [承諾された回答] としてマークできます。これは、ユーザーが回答が作成者の問題を解決したことを知るのに役立ちます。