Help us understand the problem. What is going on with this article?

CMake で C++ の DLL を C# から呼び出す VS ソリューションを作ってみた

More than 3 years have passed since last update.

作ったものはこちらです。

C# の exe ファイルから c++ で書かれた dll 内の helloworld な API を呼び出すだけのシンプルなサンプルです。

備忘録的メモ

環境

  • Windows 7
  • CMake 3.9.3
  • Visual Studio Community 2017

ディレクトリ構成

以下のような構成。

+-build/
| +-CMakeGenerate.bat
| +-project/
|   +-DEBUG/
|   +-RELEASE/
|   +-ソリューションファイルなど
|
+-src/
  +-DllCaller/
  | +-CMakeLists.txt
  | +-main.cs
  |
  +-HelloWorldDll/
  | +-CMakeLists.txt
  | +-helloworld.cpp
  | +-helloworld.h
  |
  +-CMakeLists.txt

build ディレクトリに入って CMakeGenerate.bat を走らせると,projet ディレクトリにソリューションが作成される。 ソリューションをビルドすると,ビルド設定に応じて DEBUG なり RELEASE なりのディレクトリが作られて,exe や dll はその中に配置される作戦。

各ファイルの働き

build/CMakeGenerate.bat

project ディレクトリを作成して,その中で cmake を読んで Visual Studio のソリューションを作る。

src/CMakeLists.txt

set(CMAKE_SUPPRESS_REGENERATION true)

ZERO_CHECK プロジェクトは特に必要ない。 なので CMAKE_SUPPRESS_REGENERATION を true にセットして,このプロジェクトが生成されないようにする。

project(CSharpWithCppDLL)

ソリューション名の定義。 ここでソリューション名の定義と一緒に言語 (C# と C++) を有効化しても良さそう。

set(CMAKE_CONFIGURATION_TYPES Debug Release)

この設定を明示的に与えない場合,MinSizeRel などのビルド設定が追加される。 自分の場合,ビルド設定は Debut と Release があれば十分なので,上の設定をしておく。

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/DEBUG")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/DEBUG")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/RELEASE")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE "${CMAKE_BINARY_DIR}/RELEASE")

EXE から DLL を呼び出す都合上,これらの出力先ディレクトリをまとめておきたい。 というわけで上のような設定をしておく。 CMAKE_RUNTIME_OUTPUT_DIRECTORY は,EXE ファイルの出力先ディレクトリを指定するもの。 同様に,CMAKE_LIBRARY_OUTPUT_DIRECTORY は DLL の出力先を指定する。

これらのプロパティ名の末尾にビルド設定名を付加することで,ビルド設定毎に異なるディレクトリに出力することができる。 これによって,上記のように Debug と Release で出力ディレクトリを分けることができる。

add_subdirectory(DLLCaller)
add_subdirectory(HelloWorldDll)

Dll 呼び出し用の C# の exe と,C# から呼び出される C++ の dll を定義するサブディレクトリをソリューションにに追加する。

set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT DllCaller)

最後に,DllCaller (C# の exe) のプロジェクトを Visual Studio のスタートアッププロジェクトに設定しておく。

src/DllCaller/CMakeLists.txt

cmake_minimum_required(VERSION 3.8)
enable_language(CSharp)
add_executable(DllCaller main.cs)

C# を使えるように enable_language して,ソースファイルを追加しているだけ。

src/HelloWorldDll/CMakeLists.txt

cmake_minimum_required(VERSION 3.8)
enable_language(CXX)
add_library(HelloWorldDll
  SHARED
  helloworld.h
  helloworld.cpp
)
add_definitions(-DDLL_EXPORT)

enable_language で C++ を有効化した後,DLL 生成用のプロジェクトを追加している。 DLL を作成する場合には,add_library の第 2 引数に SHARED を渡す (この引数に STATIC を渡すと,.lib ファイルが作成されるプロジェクトになる)。

最後の add_definitions は,helloworld.h の中でのコンパイルスイッチを操作するためのもの。 この行を追加することで,コンパイル時に DLL_EXPORT が define され,helloworld.h にて __declspec(export) が使われるようになる。

guttally
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away