OPENCVのプログラムをビルドなしでgcc(Mingw)でコンパイルできるように改造したい。

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 3,644

carnage0216

score 133

環境 

  • Windows10 64bit
  • OPENCV3.2.0
  • gcc(mingw)

OPENCVのプログラムがVSでしかビルドできないことはわかっています。
しかし、プログラムを改造することでgccでもコンパイルできると思うのですが、
どこをどのように改造すればよいかわかりません。
何かヒントを頂けないでしょうか?(それ以前にビルドなしでプログラムを改造しただけでgccでコンパイルできるようにすること自体が可能なのかも方法とは別にお聞きしたいです。)
コンパイラgccをいじることでも以下のプログラムをコンパイルすることを可能にできる気もしますが、さすがにコンパイラをいじるのは至難の業なので、プログラムの方をいじってgccでもコンパイルできるようにしたいと考えました。
どうかよろしくお願いいたします。
gccでコンパイルできるように改造したいプログラムはこちらです。

#include <opencv2/opencv.hpp>
#include <opencv2/opencv_lib.hpp>
#include <opencv2/highgui/highgui.hpp>

int main(void)
{
  cv::Mat src_img;
  src_img = cv::imread("ファイルパス", 1);
  // 画像が読み込まれなかったらプログラム終了
  if(src_img.empty()) return -1;

  // 結果画像表示
  cv::namedWindow("Image", CV_WINDOW_AUTOSIZE|CV_WINDOW_FREERATIO);
  cv::imshow("Image", src_img);
  cv::waitKey(0);
}


<編集1>
cmake、ビルドなしでプログラムの改造のみでgccコンパイラは使えないでしょうか?
丸投げの質問で申し訳ありません。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    2018/05/04 09:41

    複数のユーザーから「やってほしいことだけを記載した丸投げの質問」という意見がありました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

回答 5

checkベストアンサー

+9

この質問を見て、「なぜVC++で作成されたC++のDLLをMinGWでは使用できないのか?」と疑問に思っている人もいると思いますので、解説します。読みたい人だけ読んでください。


DLLの仕組みはCの時代からあまり変わっていません。C++にはクラスがありますが、DLL自体に何々クラスというのが存在するわけではありません。また、C++にはオーバーロードがありますが、この関数はオーバーロードするという情報が存在するわけではありません。実体は全て、Cと同じようにただの関数です。いってしまえば、DLLは関数名とそのエントリーポイントだけが公開されており、呼び出し側は目的の関数のエントリーポイントを探して、呼び出すだけという仕組みです。

問題はこの関数名をどうするかと言うことになります。C++にはCにはなかったクラスやテンプレート、名前空間、オーバーロード等があり、C++上では一つの関数名が複数の実装になったりします。しかし、エントリーポイントは一つしかないため、これらは別々の関数として登録しなくてはなりません。そして、実際にDLL上では別々の関数として登録されています。

つまり、C++をDLL化した場合、クラスやテンプレート、名前空間、オーバーロードによって一意に決まる名前の関数として登録しているに過ぎません。問題はこの一意に決まる名前をどうやって決めるかですが、この決め方はコンパイラによって異なります。さらに、VC++ではバージョンによっても異なります。

VC++でDLLを作成した場合、VC++における規則でDLLに登録される名前が決定されます。同じVC++では同じ規則で変換するので、その関数を見に行く事が出来るという仕組みです。しかし、MinGW等の別のコンパイラでは異なる規則を用いています。そのため、DLLに登録されている関数が見つけられず、使用することが出来ないというのが真相になります。

参考: c++ - Linking to MSVC DLL from MinGW - Stack Overflow

なお、Cの関数(C++内ならexport "C"された関数)はそのままの名前でDLLに登録されるため、上記のような問題は起きません。そのため、VC++側でCの関数で出来たラッパーを作るという手段もありますが、簡単にできるような方法は見つけられませんでした。

名前だけの問題であれば、エイリアスを用意することで無理矢理使用することは出来ます(実際の例は後述)。ただし、名前が異なるだけではなく、内部の構造もコンパイル依存の所が存在するため、必ずうまくいくとは限りません。手動でエイリアスを用意するなどの苦労するばかりか、うまくいかなくて徒労に終わる可能性が高いため、推奨は出来ません。


ついでに、この質問を読んで疑問に思った方への補足です。これまでの質問にあった皆さんの優れた回答を読んでいなかった人達もいるかと思いますので、参考にしてください。

  • OpenCV 3.4.1の公式バイナリのWindows版はVisual Studio 2015とVisual Studio 2017のVC++用にコンパイルされています。DLLおよびLIBはその二つから使えるようになっていますが、MinGW GCC等のVisual Studio以外のコンパイラから使用できるようにはなっていません(理由は上で述べたとおりです)。MinGW GCC用のバイナリは公式にはありません。
  • MSYS2にはOpenCVのバイナリパッケージ(mingw-w64-x86_64-opencvとmingw-w64-i686-opencv)が存在します。そちらを使えばMSYS2環境でのMinGW GCCでOpenCVを使ったプログラムをコンパイルすることは可能です。OpenCV自体をMSYS2上でコンパイルするためのパッチおよび手順もMSYS2のレポジトリに公開されています。
  • OpenCVはCmakeを使うことを前提に設計されています。OpenCVをコンパイルする場合はCmakeを用いて依存関係を解決したMakefileやVisual Studioのプロジェクトファイルを作る必要があります。OpenCVを使うプログラムを作る場合も、Cmakeで依存関係を解決できるようにCmakeのファイルが用意されています。
  • OpenCVの公式バイナリや上記のMSYS2パッケージはCUDAが有効になっていません。CUDAを使用したい場合は自分でコンパイルする必要があります。
  • OpenCV 3からCのAPIは非推奨になり、C++のAPIを使うことが推奨されています。しかし、CのAPIを使用できないわけではありません。
  • Cmakeは依存関係等を解決してMakefileやVisual Studioのプロジェクトファイルを作成するツールです。往年のautomakeに取って代わるツールですが、UNIX/Linux環境のみならず、WindowsでのVisual Studioにも対応しているなど、マルチプラットフォームなC/C++プログラムで特に使われるようになっているツールです。

 OpenCVの公式バイナリをMinGW GCCから無理矢理使う方法

MSYS2+MINGW64環境で実施します。GCCおよびdlltool等はインストール済みとします。また、VS2017のランタイムもインストール済みとします。特に明記しませんが、Windows 10の64bit環境です。$はシェルのプロンプトになります。

1, 作業フォルダーにソースコード"sample.c"を置き、次のように書き換えます。(画像のファイル名を設定し、不要なヘッダを削除しただけです)

sample.c

#include <opencv2/opencv.hpp>

int main(void)
{
    cv::Mat src_img;
    src_img = cv::imread("sample.jpg", 1);
    // 画像が読み込まれなかったらプログラム終了
    if (src_img.empty()) return -1;

    // 結果画像表示
    cv::namedWindow("Image", CV_WINDOW_AUTOSIZE | CV_WINDOW_FREERATIO);
    cv::imshow("Image", src_img);
    cv::waitKey(0);
}

2, 適当なJPEGファイルを作業フォルダーにおいて、"sample.jpg"という名前にします。

3, OpenCVのWindows版公式バイナリopencv-3.4.1-vc14_vc15.exeを実行し、Cドライブ直下にインストールします。"C:\opencv\build\x64\vc15\bin\opencv_world341.dll"を作業フォルダーにコピーします。

$ cp /c/opencv/build/x64/vc15/bin/opencv_world341.dll .

4, 下記内容のDEFファイル"opencv_world341_gcc.def"を作成します。

opencv_world341_gcc.def

LIBRARY "opencv_world341.dll"
EXPORTS
; cv::String::allocate(unsigned long long)
?allocate@String@cv@@AEAAPEAD_K@Z
_ZN2cv6String8allocateEy==?allocate@String@cv@@AEAAPEAD_K@Z
; cv::Mat::deallocate()
?deallocate@Mat@cv@@QEAAXXZ
_ZN2cv3Mat10deallocateEv==?deallocate@Mat@cv@@QEAAXXZ
; cv::fastFree(void*)
?fastFree@cv@@YAXPEAX@Z
_ZN2cv8fastFreeEPv==?fastFree@cv@@YAXPEAX@Z
; cv::imread(cv::String const&, int)
?imread@cv@@YA?AVMat@1@AEBVString@1@H@Z
_ZN2cv6imreadERKNS_6StringEi==?imread@cv@@YA?AVMat@1@AEBVString@1@H@Z
; cv::String::deallocate()
?deallocate@String@cv@@AEAAXXZ
_ZN2cv6String10deallocateEv==?deallocate@String@cv@@AEAAXXZ
; cv::namedWindow(cv::String const&, int)
?namedWindow@cv@@YAXAEBVString@1@H@Z
_ZN2cv11namedWindowERKNS_6StringEi==?namedWindow@cv@@YAXAEBVString@1@H@Z
; cv::imshow(cv::String const&, cv::_InputArray const&)
?imshow@cv@@YAXAEBVString@1@AEBV_InputArray@1@@Z
_ZN2cv6imshowERKNS_6StringERKNS_11_InputArrayE==?imshow@cv@@YAXAEBVString@1@AEBV_InputArray@1@@Z
; cv::waitKey(int)
?waitKey@cv@@YAHH@Z
_ZN2cv7waitKeyEi==?waitKey@cv@@YAHH@Z

5, 下記コマンドを実行し、libopencv_world341.aを作成します。

$ dlltool -D opencv_world341.dll -d opencv_world341_gcc.def -l libopencv_world341_gcc.a

6, 作成したライブラリにリンクしてコンパイルします。

$ g++ -O2 -Wall -std=c++17 -I/c/opencv/build/include -L. sample.cpp -lopencv_world341_gcc -o sample.exe

7, MSYS2環境でsample.exeを実行できるか確認します。

$ ./sample.exe

8, エクスプローラー上でも実行できるように依存関係のDLLをコピーしておきます。

$ cp /mingw64/bin/libgcc_s_seh-1.dll .
$ cp /mingw64/bin/libstdc++-6.dll .
$ cp /mingw64/bin/libwinpthread-1.dll .

9, エクスプローラー上でsample.exeをダブルクリックすると画像が表示されます。

これで完了です。お疲れ様でした。シンボル名を調べるのは二度とやりたくないです。なお、この方法は必ずうまくいくとは限らず、今回はたまたまうまくいっただけに過ぎません。私もよくわかっていない(特にDEFファイルが未だによくわからない)ため、解説はありません。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/04 09:37

    はじめまして

    ・技術的考察が必要
    ・ベストではなくベターな解決を探す そのためには自ら決めた技術的制約も見直さないといけない

    そういう課題を この質問者さんの質問から自分は読み取りました。

    解説も丁寧で正しいと ”自分は”思いましたので
    高評価つけさせていただきます。

    (読みたい人だけ読んでください。は不要ですよ、解説しますでOK)

    キャンセル

+3

こんにちは。

OPENCVのプログラムがVSでしかビルドできないことはわかっています。

そんなことないです。OpenCVはMinGWでもビルドできるようです。MinGWでビルドしたOpenCVとリンクすればMinGWでOpenCVを使うプログラムもビルドできますよ。

mingwでopencvビルドしてみた
An Instllation of OpenCV 3.2.0 on Windows10 using msys2

cmake、ビルドなしでプログラムの改造のみでgccコンパイラは使えないでしょうか?

MinGWでビルドされたOpenCVを入手できれば使えますよ。
MinGWでOpenCVをビルドした人はそこそこいるようですから、探せばあるかも知れません。
30分くらい探して見つからなければビルドした方が速いような気もしますが。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/04 04:21

    Chironianさんが提示されているサイトをお読みになったのでしょうか。

    キャンセル

  • 2018/05/04 04:37

    carnage0216さん。
    一般にヘッダファイルをコンパイラ別に用意することはないです。単なるソース・ファイルですし、ほとんど同じものでよいですから。どうしても異なる部分は事前定義マクロでコンパイルする部分を切り替えます。

    OpenCVの開発者はOpenCVをビルドするためにCMakeを使うことを選択し、CMakeを使ってビルドできるように各種の設定ファイルやスクリプトを用意しています。それらを使わないでOpenCVをビルドすることも原理的には不可能ではないですが、ぞっとする程苦労するでしょう。
    なぜ、開発者が準備し、多くの人ができることを報告している方法でやろうとしないのでしょうか?

    > ただCmakeにはVS用にビルドするツールがあるためみなさんが使っているのだと考えます。

    私がご提示したサイトにはCMakeを使ってOpenCVをMinGW用にビルドする手順が書かれていますよ?

    キャンセル

  • 2018/05/04 05:13

    私の書き方が悪かったです。決してcmakeを使いたくないわけではなく使わない方法があるのか気になってしまっただけです。
    早速ビルドしてみます。
    どうもありがとうございます。

    キャンセル

+3

※ 回答ではありませんごめんなさい

通常ライブラリ(ここではOpenCV)の作者はユーザに対し"環境が違ってもコード自体は変更不要(orほんのちょっと)"となるよう工夫するでしょうし、実際OpenCVもそうなっています。環境(OS/compiler)の違いをヘッダとライブラリで吸収してくれています。

それを踏まえて:

プログラムを改造することでgccでもコンパイルできると思うのですが、

そう考えた理由/根拠は?

あなたはこれまでに:

OpenCVのヘッダを #include せずにコンパイルしたい
OpenCVライブラリなしにコンパイルしたい

などなど、「なんでそんなことしたいの? / なぜフツーにコンパイル/リンクしないの?」
な質問を挙げています。
一体どんな意図があってこんな質問を続けるんです?

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/05 00:14

    はい。以後気を付けます。
    どうにかしてほしいわけではありません。口癖で出てしまいます。

    キャンセル

  • 2018/05/05 00:15 編集

    出すな。堪えろ。回答者を不快にさせる。事実僕は不快だ。

    キャンセル

  • 2018/05/05 00:16

    はい。わかりました。

    キャンセル

+1

こちらの記事は参考になりますか。

Using OpenCV with gcc and CMake

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/05/04 02:02

    どうもありがとうございます。

    キャンセル

+1

OPENCVのプログラムがVSでしかビルドできないことはわかっています。

適切にcmake(+必要に応じてMSYS)を用いればビルドはできますね。

しかし、プログラムを改造することでgccでもコンパイルできると思うのですが、
どこをどのように改造すればよいかわかりません。
何かヒントを頂けないでしょうか?(それ以前にビルドなしでプログラムを改造しただけでgccでコンパイルできるようにすること自体が可能なのかも方法とは別にお聞きしたいです。)

OpenCVの規模に対しては無謀ですね。
環境切り分けのために定義しているマクロの調査
cmakeの仮定で生成されるファイルの調査など大掛かりな作業が必要になります。

VCでビルドしたDLLのCインタフェースに対してダイナミックリンクするって方法はありますが
特段優位性があるわけでもないので
OpenCVライブラリ作成者の意図通りにcmakeしてビルドしてリンクした方が無難でしょう。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.21%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる
  • トップ
  • Cに関する質問
  • OPENCVのプログラムをビルドなしでgcc(Mingw)でコンパイルできるように改造したい。