exportしたいクラスのメンバにSTLが存在するためコンパイルすると警告が出る

解決


友理奈  2005-04-22 05:39:51  No: 57145

DLLを作成しています。
クラスのエクスポートをしようとしています。

エクスポートをしたいのですが、
エクスポートしたいクラスのメンバには、
stl::listや、stl::vectorが含まれています。

クラスをエクスポートするときは、
エクスポートしたいクラスの基底クラスや、
そのメンバになっているクラスも
エクスポートしなければならないため、かどうか
現状ではwarning C4251が出ます。
(STLなどが含まれていないクラスはエクスポートできています)

しかし、stl::listや、stl::vectorは、
VC付属のものですので、ヘッダを変更することができません。
エクスポートのためのDEFファイルもありません。
(そもそも、クラスエクスポートの際のDEFの記述がどうなるのかわかりません)

どうすればよいでしょうか。

CランタイムライブラリにはDLL版がありますけど、STLにはないのでしょうか。
テンプレートの性質上DLLにはなじまないのかもしれませんが……。

設計上、エクスポートしたいクラスにSTLが入っていること自体がおかしいのかもしれません。
その場合はどういった手段が考えられますでしょうか。STLを除くしかないでしょうか。

何かヒントがあれば、
どんなものでも良いので、
よろしくお願いします。


楽園  2005-04-22 07:35:02  No: 57146

クラスの export は __declspec(dllexport) でする。定義ファイルはつかわない。
STL(テンプレート)でも、bindされたものはテンプレート宣言をかいてそこに export を指定すればいい。
テンプレート自体の export はサポートしてる処理系がほぼないから規格上許可されても現実的に無理。
MSDNでATLについて調べるとSTLコレクションを使うための技術説明がある。参考にするといい。(ATL、STLなどで検索しよう


友理奈  2005-04-22 22:54:18  No: 57147

楽園さんありがとうございます。
テンプレート宣言を書くと確かに警告が出なくなりましたが、std::listが依存しているクラスがたくさんあって、それらも全部宣言しなければならないようで、まだ警告が出ないところまで行っていません。がんばります。
あと、MSDNをATL、STLで調べるといろいろ出てきました。たくさん知らない言葉が出てきて大変です。がんばります!

私のほうにも勘違いなどありましたので
一応私のしたいことをもう少し具体的に補足します。
・したいのは、STLを含むクラスのエクスポートです。
・DLL利用側も、DLL側も、全ソースコードが私の管理下にあります。
・DLL利用側に基底クラスがあります。このクラスは純粋仮想関数のみを含むクラスです。
・そのクラスをDLL側で派生させたクラスをエクスポートしたいと思っています。
・実際にexportしたい(DLL利用側で使用したい)のは、そのクラスの生成関数と、DLL側でオーバーライドしたpublicメソッドのみです。STLはクラスのprivateメンバだからDLL利用側では使用しません。メソッドはvtblから呼び出されるでしょうから、要はSTLを無視できれば良いのでは?  と思っています。だから、まったく問題の解決にはなっていませんが、C4251警告を無視すればよいだけかなぁ、と思っています。

関係ありそうなところ
http://www.tietew.jp/cppll/archive/8444
ここでは、クラス全体に  _declspec(dllimport)  を付けず、メソッドごとにつけておられますね。


友理奈  2005-04-22 22:56:29  No: 57148

上記投稿修正します。
誤  _declspec(dllimport)
正  _declspec(dllexport)


友理奈  2005-04-23 00:24:05  No: 57149

続報です。
http://forums.belution.com/ja/vc/000/116/93s.shtml
warningを出さないようにすればよいよという意見。

http://www.hey-to.net/ML-archive/vcppML/2000/msg07943.html
テンプレート宣言すればよい、というご意見。
これは楽園さんと同じご意見ですね。
なぜ私はテンプレート宣言がうまくいかないのか……。

http://www.hey-to.net/ML-archive/vcppML/2000/msg08073.html
ポインタにすればよいよという意見。
ラッパクラス作るにしても宣言は公開するわけですし、結局はポインタって事ですよね。vectorとかをnewしたことないんですけど……。まあ、できそうではあります。

http://support.microsoft.com/kb/q168958/
「STL オブジェクトであるデータ メンバが含まれるクラスをエクスポートする方法」
ってそのものずばりありますよ!
「現在エクスポートできる唯一の STL コンテナは vector です。そのほかのコンテナ (つまり、map、set、queue、list、deque) にはすべて、ネストしたクラスが含まれており、エクスポートすることはできません。」
ええっ……。そんな……。
なるほど、vectorのテンプレート宣言はうまくいくようですね。
listがだめなのか……。listが入ってるんですけど……。だめでしょうか……。
ポインタにしようかな……。


一縷の望み  2005-04-23 01:13:11  No: 57150

How To Exporting STL Components Inside & Outside of a Class
.............................
APPLIES TO
•  Microsoft Visual C++ 5.0 Enterprise Edition  
•  Microsoft Visual C++ 6.0 Enterprise Edition  
•  Microsoft Visual C++ 5.0 Professional Edition  
•  Microsoft Visual C++ 6.0 Professional Edition  
•  Microsoft Visual C++ 6.0 Standard Edition

VC.NET2003ならどうだろう?
(STLは.NET以前/以降で、templete 対応のため大変更されてます)


友理奈  2005-04-25 23:59:17  No: 57151

一縷の望みさん補足ありがとうございます。
VC.NET2003でも同じでした。警告出ます。

一応vectorはテンプレート宣言を書くと警告は出なくなります。

template class __declspec(dllexport) std::vector<int>;
extern template class __declspec(dllimport) std::vector<int>;

listは
#pragma warning(disable:4251)
#pragma warning(default:4251)
で該当部分を囲んで警告が出ないようにしました。
特に問題はなく動いています。

解決としてよいのかどうかわかりませんが
こんなところです。

助言くださった方々、ありがとうございました。


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

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






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