A certain engineer "COMPLEX"

.NETでLinuxと遊んでみる Visual Studio Code編 第7回

Introduction


前々回は、GLibc内の関数をP/Invokeで呼び出してみました。

また、CMakeでビルドしたC++のライブラリで関数を公開してみました。

これを利用して、.NET CoreでビルドしたC#のアプリケーションから、自作のC++ライブラリの関数を呼びだしてみます。

Preparation


C#とC++の簡単なプロジェクトを用意します。
今回のサンプルは

Sample source code for Demonstration, Experiment and Test

になります。

サンプルは下記の構成になります。

  • C++
    2つのint型の引数の和を返すAdd関数を備えたSharedライブラリ
  • C#
    コマンドラインの2つの引数を整数に変換し、その引数をAdd関数に渡した結果を標準出力に表示する実行アプリ

C#

Program.cs


using System;
using System.Runtime.InteropServices;

namespace CsharpApp
{
class Program
{
[DllImport("libCppLib.so")]
private static extern int Add(int x, int y);

static void Main(string[] args)
{
var x = int.Parse(args[0]);
var y = int.Parse(args[1]);
var sum = Add(x, y);
Console.WriteLine($"{x} + {y} = {sum}");
}
}
}

C++

libCppLib.cpp


#include <iostream>

extern "C" int Add(int x, int y){ return x + y; }

CMakeLists.txt


cmake_minimum_required(VERSION 3.0.0)
project(CppLib VERSION 0.0.0)

include(CTest)
enable_testing()

add_library(CppLib SHARED CppLib.cpp)

set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)

Try


C++側は、Visual Studio Codeで、CMakeを使ってビルドします。
ビルド完了後、buildフォルダ配下にlibCppLib.soが生成されます。
このファイルをシステムの共有フォルダに移動します。
FHS (Filesystem Hierarchy Standard)のルールに従って適切なフォルダにSharedライブラリをコピーします。
今回は、/usr/local/lib64にコピーします。


$ file cp CppLib/build/libCppLib.so
CppLib/build/libCppLib.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically
linked, BuildID[sha1]=73b7791b3eeb907e40dadcfbac6ec14df4da8eef, not stripped
$ nm -D CppLib/build/libCppLib.so
0000000000000760 T Add
w _ITM_deregisterTMCloneTable
w _ITM_registerTMCloneTable
U _ZNSt8ios_base4InitC1Ev
U _ZNSt8ios_base4InitD1Ev
0000000000201028 B __bss_start
U __cxa_atexit
w __cxa_finalize
w __gmon_start__
0000000000201028 D _edata
0000000000201030 B _end
0000000000000764 T _fini
00000000000005f8 T _init
$ sudo cp CppLib/build/libCppLib.so /usr/local/lib64

きちんと、Sharedライブラリがx64形式になっていることと、Add関数が公開されていることを確認し、フォルダにコピーしています。

C#側もビルドしますが、ビルド完了後、環境変数LD_LIBRARY_PATH/usr/local/lib64を追加します。
そうしないと、C#のアプリがライブラリを見つけることができません。


$ cd CsharpApp
$ dotnet restore
$ dotnet build
Microsoft (R) Build Engine version 15.3.409.57025 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

CsharpApp -> /home/xxxxxx/Work/Demo/DotNetCoreLinux6/CsharpApp/bin/Debug/netcoreapp2.0/CsharpApp.dll

Build succeeded.
0 Warning(s)
0 Error(s)

Time Elapsed 00:00:10.24
$ export LD_LIBRARY_PATH=/usr/local/lib64:$LD_LIBRARY_PATH
$ dotnet run 2 4
2 + 4 = 6
$ dotnet run 12 664
12 + 664 = 676

期待通りの結果になりました。
環境変数LD_LIBRARY_PATHへの追加は一時的なものですので、別のシェルを立ち上げたりすると、そのシェルでは認識しないので、再度追加するか永続的に認識するよう別途対応しましょう。

Conclusion


自作ライブラリを使えるようになりました。
これによりLinuxでやれることが広がりました。

Source Code


https://github.com/takuya-takeuchi/Demo/tree/master/DotNetCoreLinux6

コメントを残す

メールアドレスが公開されることはありません。

%d人のブロガーが「いいね」をつけました。