"そこ"から這い上がるブログ

プログラミングと電子工作が趣味でそこら辺のことを備忘録的に書きつつ這い上がっていこうといったブログ。そこ這い。

自作DLLのリンカエラーについて

本題と関係ないところで長時間詰まったので、もうしないように(何度かしてる)メモ

DLLを作成し、それを別のプロジェクトで利用しようとした際に、リンカエラー(LNK2019)が出てしまう。

DLLが配布されているようなもの場合はまず自分のプロジェクト設定を疑って、対象DLLの.libファイルがちゃんとリンクされているかを確認する。

ちゃんとリンクはされている&自作の場合疑うべきは
__declspec(dllexport)  の付け忘れ
自分の場合は大体これが原因

そして、それをつけてリンカエラーは消えるけども、別のエラー(C2280)が出る場合があり、
今回はそれも当たってしまった。

std::unique_ptrを使ったstd::vectorなどのコンテナクラスを含んでいる場合に起きるエラーの様で
以下のリンク先によると

c++ - DLL exporting causing issues with unique pointers - Stack Overflow

機械翻訳

declspec(dllexport)でクラスを宣言する場合、コンパイラは、インポートモジュールに必要なものがわからないため、デフォルトのコンストラクター、コピー割り当てなどの関数を含む、クラスのすべてのメンバー関数を生成する必要があります。

これについては、C ++クラスでのdllimportおよびdllexportの使用で説明されています。 unique_ptrはコピーできないため、そのコピーコンストラクターとコピー割り当て演算子は削除され、ベクターオブジェクトがそれらを使用しようとすると、C2280エラーが発生します。

declspec(dllexport)を含めない場合、コンパイラは実際に使用される関数のみを生成し、問題のあるコピーは回避されます。この問題を回避する1つの方法は、個々のクラスメンバー関数をエクスポートすることです。

これは、それらの一部をデフォルトとして指定することを意味する場合があります。仮想関数はvtableによって処理されるため、エクスポートする必要はありません。

別の回避策は、コピーコンストラクタとコピー割り当て演算子を明示的に削除することです。これにより、デフォルトコンストラクターの作成が妨げられ、コンストラクター/割り当て関数が移動されるため、これらをデフォルト設定する必要がある場合があります。

 

class UNIQUEPTRISSUE_API ClassB {
public:
    ClassB(const ClassB &) = delete;
    ClassB &operator=(const ClassB &) = delete;
    // You may need to explicitly default these if they are used
    ClassB() = default;
    ClassB &operator=(ClassB &&) = default;
    ClassB(ClassB &&) = default;
private:
    std::vector<std::unique_ptr<ClassA>> x;
};

説明にある二つ目の方法が以上のコードで、これで自分の場合は無事解決しました……
よくわかってないで使うからこういうことになるんだなぁとしみじみ