質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

865閲覧

自作ライブラリでライブラリ側に変数を持たせる適切な方法が知りたい

退会済みユーザー

退会済みユーザー

総合スコア0

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2022/10/26 06:19

編集2022/10/31 02:03

提示コードですが以下はスプライト描画クラスなのですがこれはライブラリに変数を一つだけでいいのですがその場合どうやってライブラリ側に変数として持たせればいいのでしょうか? そもそもライブラリ側だけで使う変数を持たせるやり方は正解なのでしょうか?
現状だと頂点数は一つだけしか必要ないので外に宣言してるのですがこれは実装としていいのでしょうか?

試したこと

1,ヘッダーファイルを作成してそこにSprite sprite;と宣言
2,ヘッダーファイルを作成してそこにextern Sprite sprite;と宣言

情報
その変数はライブラリ内の複数のソースから参照されますか? 1つのソースからだけ参照されますか?

sprite変数はライブラリの外から参照されます。
windowsContextという変数はライブラリの外と中から参照されます。

そのオブジェクトはいつ生成されていつ破棄されるべきですか?

廃棄はされずプログラムが動いている間ずっと稼働しています。

知りたいこと

1,ライブラリ側に変数を持たせることが正解なのかどうか?
2,一つしか必要のないクラスどうやって適切に用意すればいいのか知りたい。

cpp

1#include "Sprite.hpp" 2#include "Transform.hpp" 3#include "Shader.hpp" 4#include "Window.hpp" 5#include <vector> 6 7std::array<FrameWork::VertexAttribute_Sprite,4> FrameWork::Sprite::vertex; 8 9/*############################################################################################ 10# コンストラクタ 11############################################################################################*/ 12FrameWork::Sprite::Sprite() 13{ 14 glGenVertexArrays(1, &vao); 15 glGenBuffers(1, &vbo); 16 17 glBindVertexArray(vao); 18 glBindBuffer(GL_ARRAY_BUFFER, vbo); 19 20 glBufferData(GL_ARRAY_BUFFER, vertex.size() * sizeof(VertexAttribute_Sprite), vertex.data(), GL_DYNAMIC_DRAW); 21 22 glBindVertexArray(0); 23 glBindBuffer(GL_ARRAY_BUFFER, 0); 24} 25 26 27/*############################################################################################ 28# テクスチャ 設定 29############################################################################################*/ 30void FrameWork::Sprite::setTexture(const int texNum,const Texture tex) 31{ 32 glBindVertexArray(vao); 33 glBindBuffer(GL_ARRAY_BUFFER, vbo); 34 35 setVertexUV(tex); 36 37 glBindTexture(GL_TEXTURE_2D, tex.id); //テクスチャバインド 38 glActiveTexture(GL_TEXTURE0 + texNum); //テクスチャ有効 39 40 glBindVertexArray(0); 41 glBindBuffer(GL_ARRAY_BUFFER, 0); 42 43} 44 45 46/*############################################################################################ 47# 描画 48############################################################################################*/ 49void FrameWork::Sprite::Render(const glm::mat4 view) 50{ 51 glBindVertexArray(vao); 52 glBindBuffer(GL_ARRAY_BUFFER, vbo); 53 54 glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(VertexAttribute_Sprite) * vertex.size(), vertex.data()); 55 56 glDrawArrays(GL_TRIANGLE_STRIP, 0, vertex.size()); //描画 57 58 glBindVertexArray(0); 59 glBindBuffer(GL_ARRAY_BUFFER, 0); 60 glBindTexture(GL_TEXTURE_2D, 0); 61} 62 63 64/*############################################################################################ 65# 頂点属性 66############################################################################################*/ 67void FrameWork::Sprite::setVertexUV(const Texture tex) 68{ 69 70 vertex[0].normal[0] = 0; 71 vertex[0].normal[1] = 0; 72 vertex[0].normal[2] = 1; 73 74 vertex[1].normal[0] = 0; 75 vertex[1].normal[1] = 0; 76 vertex[1].normal[2] = 1; 77 78 vertex[2].normal[0] = 0; 79 vertex[2].normal[1] = 0; 80 vertex[2].normal[2] = 1; 81 82 vertex[3].normal[0] = 0; 83 vertex[3].normal[1] = 0; 84 vertex[3].normal[2] = 1; 85 86 // 頂点座標 87 vertex[0].position[0] = -0.5f; 88 vertex[0].position[1] = 0.5f; 89 vertex[0].position[2] = 0; 90 91 vertex[1].position[0] = -0.5f; 92 vertex[1].position[1] = -0.5f; 93 vertex[1].position[2] = 0; 94 95 vertex[2].position[0] = 0.5f; 96 vertex[2].position[1] = 0.5f; 97 vertex[2].position[2] = 0; 98 99 vertex[3].position[0] = 0.5f; 100 vertex[3].position[1] = -0.5f; 101 vertex[3].position[2] = 0; 102 103 //UV座標 104 float sizeX = 1.0f / (float)tex.size.x; 105 float sizeY = 1.0f / (float)tex.size.y; 106 107 108 109 vertex[0].uv[0] = 0; 110 vertex[0].uv[1] = 0; 111 112 vertex[1].uv[0] = 0; 113 vertex[1].uv[1] = 1; 114 115 vertex[2].uv[0] = 1; 116 vertex[2].uv[1] = 0; 117 118 vertex[3].uv[0] = 1; 119 vertex[3].uv[1] = 1; 120 121 122/* 123 vertex[0].uv[0] = sizeX * tex.position.start.x; 124 vertex[0].uv[1] = sizeY * tex.position.start.y; 125 126 vertex[1].uv[0] = sizeX * tex.position.start.x; 127 vertex[1].uv[1] = sizeY * tex.position.end.y; 128 129 vertex[2].uv[0] = sizeX * tex.position.end.x; 130 vertex[2].uv[1] = sizeY * tex.position.start.y; 131 132 vertex[3].uv[0] = sizeX * tex.position.end.x; 133 vertex[3].uv[1] = sizeY * tex.position.end.y; 134*/ 135} 136 137 138FrameWork::Sprite::~Sprite() 139{ 140 141} 142

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

int32_t

2022/10/26 07:11

> ライブラリ側だけで使う変数を持たせる その変数はライブラリ内の複数のソースから参照されますか? 1つのソースからだけ参照されますか? そのオブジェクトはいつ生成されていつ破棄されるべきですか?
fana

2022/10/26 07:15

> ライブラリ側だけで使う変数 これに関して何が問題点なのか? 好きに実装すればよいだけであり,「ライブラリ」という言葉がどんな問題点にどう関与しているのか?も全く意味不明.
int32_t

2022/10/31 01:20 編集

変数を公開するか公開しないかの違いはありますけど、https://teratail.com/questions/tsw2bv32sx1au0https://teratail.com/questions/r5je8z2tv2kpil を聞く前にこの質問を解決した方がいいんじゃないですかね。 私は「ライブラリは変数を公開しないほうが良い」と考えていますが、その場合の代替案を書くのに情報がもっと必要なので回答はまだ書けません。
退会済みユーザー

退会済みユーザー

2022/10/31 01:53

どんな情報が必要でしょうか?
int32_t

2022/10/31 02:00

> どんな情報が必要でしょうか? 1つ目のコメントに書いてあります。
fana

2022/10/31 02:11

> ライブラリ側だけで使う変数 という話じゃなくなってるやんけ.
guest

回答2

0

ベストアンサー

質の高いライブラリでは、ライブラリからグローバル変数を公開することはとても稀です。いくつか理由はありますが、グラフィック系のライブラリだと複数のウィンドウを持つアプリでウィンドウ毎にライブラリが独立して動く必要があるとか、バイナリ互換性を保つために必要だったりとか。
Windows の DLL で変数を公開するのがトラブルの元だったような記憶もあります。


簡単な対処

グローバル変数を公開するかわりに、Getなんとか() Setなんとか() のような関数を公開しましょう。ライブラリ内部ではライブラリ内部専用のヘッダファイルを用意して、そこでグローバル変数を宣言してもよいです。

よりまともな対処

ライブラリの初期化関数があるなら、そこでグローバル変数相当の構造体のメモリを確保して、そのメモリを判別できるような情報をクライアントに返します。それ以後、ライブラリの機能を使うときには常にその情報を渡すようにAPIを設計します。ライブラリの終了関数があるなら、そこでメモリを開放します。

c++

1// ヘッダ 2struct LibrayGlobals; // これの定義はクライアントに見せない 3using LibraryHandle = LibraryGlobals*; 4 5LibraryHandle Initialize(); 6void Finalize(LibraryHandle handle); 7 8void SetWindowContext(LibraryHandle handle, WindowContext*); 9Sprite* GetSprite(LibraryHandle handle);

Windows API がこういう設計になっていて、参考になると思います。

投稿2022/10/31 03:03

int32_t

総合スコア20856

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2022/10/31 04:04

質問ですが`メモリを判別できるような情報をクライアントに返します`について詳細に知りたいです。 判別できる情報とはどういう意味なのでしょうか?
int32_t

2022/10/31 04:11

一番簡単なのは、回答の例のように構造体の内容を開示せずにポインタを返してしまうことです。
退会済みユーザー

退会済みユーザー

2022/10/31 04:40

なるほど。しかし使用側で仕方なくウインドウコンテキストを取得したい場合がある場合はどうすればいいのでしょうか? ``` /*############################################################################################ # スクリーン座標 取得 ############################################################################################*/ glm::mat4 FrameWork::Transform::getMatPosition_Sprite(const std::shared_ptr<FrameWork::Window> window)const { //UV座標 float sizeX = 1.0f / (float)window->getSize().x; float sizeY = 1.0f / (float)window->getSize().y; return glm::translate(glm::mat4(1), glm::vec3(position.x * sizeX,position.y * sizeY,position.z)); } ```
int32_t

2022/10/31 05:12

「使用側」とはライブラリの外という意味ですか? 「ウインドウコンテキスト」とはどのように利用するものなのか具体的な話がこの質問では一切説明されていないのでわかりません。
退会済みユーザー

退会済みユーザー

2022/10/31 05:21

ウインドコンテキストはウインドウ関係をまとめたものなのですがそのウインドウの現在のサイズを取得するのにどうしても必要なのですがこの場合どうするのが適切なのでしょうか? 利用側とはライブラリを使う側です。
int32_t

2022/10/31 05:40

とにかく、ライブラリ利用者が必要な情報は上記 LibraryHandle みたいなものを引数としたAPI経由で取ればいいです。LibraryHandle の値はライブラリ利用者側のグローバル変数に入れて問題ありません。
guest

0

何かよくわからんけども, とりあえず「ライブラリにしない」形について考えてみては?

すなわち,その Sprite だの何だのいうやつらのソースコードをそのまま使うのだとしたら,それらのソースコード内の実装はどうなるのか? っていう.

ライブラリにするかしないかによって,そこの実装に何か違いが出てきますか?
同じ話では?

投稿2022/10/31 02:25

編集2022/10/31 02:25
fana

総合スコア11656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2022/10/31 02:36

ざっくり言えば, A.cpp と B.cpp と C.cpp なるソースファイル群があって, これらをコンパイルしたら A.obj と B.obj と C.obj なるオブジェクトファイル群ができて, これらをリンクしたら1個の実行形式が生成できるんだけど… ↓ 「B と C の部分はAとは独立している部分だし, B.obj と C.obj の部分をまとめて BC.lib なるライブラリにしてみよう」みたいな話だよね. それをするときに B.cpp や C.cpp の実装を変える必要が生じるんか? っていう.
fana

2022/10/31 02:38

どこにどんな変数があってどう使うのか? なんてことは > A.cpp と B.cpp と C.cpp なるソースファイル群があって とかいう形に分けて実装した時点で終わってる話でしょ.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問