差分

ナビゲーションに移動 検索に移動

C♯のモジュールからC++のDLLを呼び出してみる

3,399 バイト追加, 2019年7月26日 (金) 16:46
<amp/>= インストール =とても簡単で、以下のコマンドを実行して、ReadyMediaをインストールするだけです。<pre>sudo apt-get install minidlna</pre>久しぶりにやったら、すっかり忘れていたので覚書…
= 準備 = C++のDLLプロジェクト作成 ==DLNAで共有?するためのディレクトリを適当に作成します。<br/>まず、C++のDLLを作成するときの注意点…今回は、「/share」ディレクトリを作成し、その配下に「movies」「photos」「musics」のディレクトリを作成し、それを共有するようにしてみます。作成するプロジェクトは、「Win32プロジェクト」を選択するんだ。<br/>以下のコマンドを実行して、それぞれのディレクトリを作成します。<syntaxhighlight lang="bash">sudo mkdir /sharesudo mkdir /share/moviessudo mkdir /share/photossudo mkdir /share/musics</syntaxhighlight>※ディレクトリパスは環境に合わせて変更してください。[[ファイル:CShapeToCppDll-005.jpg]]
また、ReadyMediaがアクセスできるように各ディレクトリの所有権を変更します。
<syntaxhighlight lang="bash">sudo chown pi:pi /share
sudo chown pi:pi /share/movies
sudo chown pi:pi /share/photos
sudo chown pi:pi /share/musics</syntaxhighlight>
= 設定 =あと…アプリケーションの設定では「DLL」と「空のプロジェクト」を選択してね。<br/>「/etc」ディレクトリに「minidlna[[ファイル:CShapeToCppDll-001.conf」ファイルが作成されるので、「nano」等のエディタで設定を変更します。jpg]]<br/>(デフォルトで「media_dir=/var/lib/minidlna」が設定されています。必要に応じてコメントアウトしてください。)
== 共有設定 ==
=== 動画の共有 ===
明示的に動画を共有したい場合は、「minidlna.conf」に以下の行を追記します。
<pre>media_dir=V,/share/movies</pre>
=== 画像の共有 ===動画と同様に、画像を共有したい場合は、「minidlna空のプロジェクトが作成されたら「cpp」「h」「def」ファイルを追加するんだ。今回は「CppDll.conf」に以下の行を追記します。<pre>media_dir=P,/share/photos</pre>cpp」「CppDll.h」「CppDll.def」を追加したよ。
=== 音楽の共有 ===
音楽を共有したい場合は、「minidlna.conf」に以下の行を追記します。
<pre>media_dir=M,/share/musics</pre>
=== 組み合わせ ===例えばディレクトリに動画と画像が保存されていて、両方共有したい場合は、以下の様に設定します。そしたら、プロジェクトのプロパティを開いて「構成プロパティ→リンカー→入力→モジュール定義ファイル」に「CppDll.def」を設定するんだ。<br/>(DebugとReleaseでそれぞれ設定する必要があるんだよ。)<prebr/>media_dir=VP,/share/MoviesAndPhotos[[ファイル:CShapeToCppDll-002.jpg]]<br/pre>
== 新しいファイルの監視 DLLのコード ===== ヘッダーファイル(*.h) ===ファイルを格納したときに、自動的に共有する設定をします。<br/syntaxhighlight lang="cpp">【修正前】#ifndef DLLAPI<pre>#inotify=yes</pre>define DLLAPI extern "C" __declspec(dllimport)【修正後】<pre>inotify=yes</pre>#endif
DLLAPI long __stdcall _Sum(const long p_Number1, const long p_Number2);
</syntaxhighlight>
また監視間隔を設定します。<br/>【修正前】<pre>#notify_interval=895</pre>【修正後】== コードファイル(*.cpp) ===<pre>notify_intervalsyntaxhighlight lang=60</pre"cpp">(単位は「秒」です。上記の例では1分間隔で監視します)#define DLLAPI
#include "CppDll.h"
監視が必要なファイル数が非常に多い場合は、以下のコマンドを実行してファイル数を増やしておく必要があります。<br/>DLLAPI long __stdcall _Sum(const long p_Number1, const long p_Number2)(デフォルトは8192です){ return p_Number1 + p_Number2;}<syntaxhighlight lang="bash">sudo sysctl fs.inotify.max_user_watches=100000</syntaxhighlight>
=== モジュール定義ファイル(*.def) ===
<syntaxhighlight lang="text">
LIBRARY CppDll
ただ…このままだと再起動すると値がもとに戻ってしまいます。<br/>EXPORTSそこで「/etc/sysctl.conf」に以下の行を追記します。 _Sum<syntaxhighlight lang="bash">fs.inotify.max_user_watches=100000</syntaxhighlight>
== C♯のプロジェクト作成 ==
ほとんどそのまま作るんだけど…ソリューションのコンパイル対策をしておくよ。
= コマンド =インストールした状態でサービスは有効になっていますが…各コマンドは以下のとおりです。== 起動 ==<syntaxhighlight lang="bash">sudo /etc/init.d/minidlna start</syntaxhighlight>=ビルドイベントの設定 = 終了 ==C++のDLLはソリューションフォルダ直下の「Debug」や「Release」フォルダにDLLが格納されてしまうんだ。そうすると、デバッグするときにDLLが見つからないので、ビルドイベントを使ってコピーしてしまうよ。以下のように設定してね。(「Release」コンパイルするまでは「Release」フォルダがないのでコメントアウトしているよ)<syntaxhighlight lang="bash">sudo br/etc/init.d/minidlna stop</syntaxhighlight>== 状態確認 ==<syntaxhighlight lang="bash">sudo /etc/init[[ファイル:CShapeToCppDll-004.d/minidlna statusjpg]]<br/syntaxhighlight>
= 参考サイト == プロジェクトの依存関係の設定 ===[http://www.lanhome.co.jp/device/raspberry-pi.html Raspberry Piを用いたDLNAホームサーバー|Lanhome]コピーするにもちゃんとリコンパイルされた資源をコピーしないといけないので、プロジェクトの依存関係を設定することで、ビルドの順番を設定するよ。<brBr/>[https://wiki.archlinux.jp/index.php/ReadyMedia ReadyMedia - ArchWiki]ソリューションエクスプローラーからC♯のプロジェクトを右クリックして「ビルド依存関係」→「プロジェクト依存関係」を選択してね。<br/>[https://www.wassyoi-hack.com/solve_no_space/ ラズパイのNo space left on deviceに対処する方法]「依存関係」タブの依存先にC++のプロジェクトが表示されているはずだから、チェックを入れてOKボタンをクリックしてね。
== C♯のコード ==MVVMモデルでサンプルを作ったからビューモデルが入っているけど…DLLを呼ぶには必要ないから無視してね。=== モデル ===<syntaxhighlight lang="C#">using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Imaging;using System.Windows.Navigation;using System.Windows.Shapes; //追加using System.Runtime.InteropServices; namespace CSharpToCDLL{ /// <summary> /// MainWindow.xaml の相互作用ロジック /// </summary> public partial class MainWindow : Window { /// <summary> /// DLLの関数定義 /// </summary> /// <param name="p_Number1">数値1</param> /// <param name="p_Number2">数値2</param> /// <returns>合計</returns> [[CategoryDllImport("CppDll.dll")] private extern static Int32 _Sum(Int32 p_Number1,Int32 p_Number2);  /// <summary> /// 標準のコンストラクタ /// </summary> public MainWindow() { InitializeComponent(); }  /// <summary> /// ボタンクリックイベントハンドラ /// </summary> /// <param name="sender">イベント送信元</param> /// <param name="e">イベント情報</param> private void Button_Click(object sender, RoutedEventArgs e) { //DLLの関数を呼び出す Int32 l_Result = _Sum(300, 500);  //計算結果の表示 MessageBox.Show("計算結果:" + l_Result.ToString()); } }}</syntaxhighlight> === ビュー ===<source lang="xml"><Window x:Class="CSharpToCDLL.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="77.056" Width="525"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="5"/> <RowDefinition Height="24"/> <RowDefinition/> <RowDefinition Height="5"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="5"/> <ColumnDefinition/> <ColumnDefinition Width="5"/> <ColumnDefinition Width="75"/> <ColumnDefinition Width="5"/> </Grid.ColumnDefinitions> <Label Grid.Row="1" Grid.Column="1" Content="{Binding Label_Content}"/> <Button Grid.Row="1" Grid.Column="3" Content="実行" Click="Button_Click"/> </Grid></Window></source>=== ビューモデル ===<source lang="csharp">using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks; //追加using System.ComponentModel; namespace CSharpToCDLL{ class MainWindowViewModel :Debian]]INotifyPropertyChanged { /// <summary> /// ラベル表示用変数 /// </summary> private String m_Label_Content;  /// <summary> /// ラベル表示文字列 /// </summary> public String Label_Content { set { this.m_Label_Content = value; this.OnPropertyChanged("Label_Content"); } get { return this.m_Label_Content; } }  /// <summary> /// プロパティ変更イベントハンドラ /// </summary> public event PropertyChangedEventHandler PropertyChanged;  /// <summary> /// プロパティ変更通知 /// </summary> /// <param name="p_PropertyName">プロパティ名</param> public void OnPropertyChanged(String p_PropertyName) { if (this.PropertyChanged != null) { this.PropertyChanged(this, new PropertyChangedEventArgs(p_PropertyName)); } } }}</source> [[Category:RaspbianC♯]][[Category:Raspberry PiC++]][[Category:DLNAdll]]

案内メニュー