ページ「Dropboxのインストール/Debian9.9」と「C♯のモジュールからC++のDLLを呼び出してみる」の間の差分

提供: とある社畜の頭脳整理
(ページ間の差分)
ナビゲーションに移動 検索に移動
 
 
1行目: 1行目:
= GUIインストール =
+
久しぶりにやったら、すっかり忘れていたので覚書…
GUIが利用できる「nautilus-dropbox」を入れていこうと思います。<br/>GNOMEデスクトップ前提なので、GNOMEを使っていない人は、別のパッケージを選択する必要があります。
 
  
== 「sources.list」の確認 ==
+
== C++のDLLプロジェクト作成 ==
今回インストールしようとしている「nautilus-dropbox」は「Non-Freeディストリビューション」に含まれています。<br/>安定版(mainディストリビューション)をインストールしている場合などは、そのままではインストールすることができません。<br/>なので、「sources.list」を加工して「Non-Freeディストリビューション」もインストールできるようにします。
+
まず、C++のDLLを作成するときの注意点…
 +
作成するプロジェクトは、「Win32プロジェクト」を選択するんだ。<br/>
 +
[[ファイル:CShapeToCppDll-005.jpg]]
  
「sources.list」ファイルは「/etc/apt」ディレクトリにあります。<br/>修正前は以下の様になっているかと思います。
 
<syntaxhighlight lang="text" line>#
 
  
# deb cdrom:[Debian GNU/Linux 9.9.0 _Stretch_ - Official amd64 NETINST 20190427-10:30]/ stretch main
+
あと…アプリケーションの設定では「DLL」と「空のプロジェクト」を選択してね。<br/>
 +
[[ファイル:CShapeToCppDll-001.jpg]]<br/>
  
#deb cdrom:[Debian GNU/Linux 9.9.0 _Stretch_ - Official amd64 NETINST 20190427-10:30]/ stretch main
 
  
deb http://ftp.jp.debian.org/debian/ stretch main
+
空のプロジェクトが作成されたら「cpp」「h」「def」ファイルを追加するんだ。今回は「CppDll.cpp」「CppDll.h」「CppDll.def」を追加したよ。
deb-src http://ftp.jp.debian.org/debian/ stretch main
 
  
deb http://security.debian.org/debian-security stretch/updates main
 
deb-src http://security.debian.org/debian-security stretch/updates main
 
  
# stretch-updates, previously known as 'volatile'
+
そしたら、プロジェクトのプロパティを開いて「構成プロパティ→リンカー→入力→モジュール定義ファイル」に「CppDll.def」を設定するんだ。<br/>
deb http://ftp.jp.debian.org/debian/ stretch-updates main
+
(DebugとReleaseでそれぞれ設定する必要があるんだよ。)<br/>
deb-src http://ftp.jp.debian.org/debian/ stretch-updates main</syntaxhighlight>
+
[[ファイル:CShapeToCppDll-002.jpg]]<br/>
  
要は「stretch mainからしか取得しませんよ」ってなっています。
+
== DLLのコード ==
 +
=== ヘッダーファイル(*.h) ===
 +
<syntaxhighlight lang="cpp">
 +
#ifndef DLLAPI
 +
#define DLLAPI extern "C" __declspec(dllimport)
 +
#endif
  
これを以下の様に修正します。
+
DLLAPI long __stdcall _Sum(const long p_Number1, const long p_Number2);
 +
</syntaxhighlight>
  
<syntaxhighlight lang="text" highlight="7,8,10,11,14,15" line>#  
+
=== コードファイル(*.cpp) ===
 +
<syntaxhighlight lang="cpp">
 +
#define DLLAPI
  
# deb cdrom:[Debian GNU/Linux 9.9.0 _Stretch_ - Official amd64 NETINST 20190427-10:30]/ stretch main
+
#include "CppDll.h"
  
#deb cdrom:[Debian GNU/Linux 9.9.0 _Stretch_ - Official amd64 NETINST 20190427-10:30]/ stretch main
+
DLLAPI long __stdcall _Sum(const long p_Number1, const long p_Number2)
 +
{
 +
return p_Number1 + p_Number2;
 +
}
 +
</syntaxhighlight>
  
deb http://ftp.jp.debian.org/debian/ stretch main non-free
+
=== モジュール定義ファイル(*.def) ===
deb-src http://ftp.jp.debian.org/debian/ stretch main non-free
+
<syntaxhighlight lang="text">
 +
LIBRARY CppDll
  
deb http://security.debian.org/debian-security stretch/updates main non-free
+
EXPORTS
deb-src http://security.debian.org/debian-security stretch/updates main non-free
+
_Sum
 +
</syntaxhighlight>
  
# stretch-updates, previously known as 'volatile'
+
== C♯のプロジェクト作成 ==
deb http://ftp.jp.debian.org/debian/ stretch-updates main non-free
+
ほとんどそのまま作るんだけど…ソリューションのコンパイル対策をしておくよ。
deb-src http://ftp.jp.debian.org/debian/ stretch-updates main non-free</syntaxhighlight>
 
  
これで、「non-freeディストリビューション」から取得できるようになりました。
+
=== ビルドイベントの設定 ===
 +
C++のDLLはソリューションフォルダ直下の「Debug」や「Release」フォルダにDLLが格納されてしまうんだ。そうすると、デバッグするときにDLLが見つからないので、ビルドイベントを使ってコピーしてしまうよ。以下のように設定してね。(「Release」コンパイルするまでは「Release」フォルダがないのでコメントアウトしているよ)<br/>
 +
[[ファイル:CShapeToCppDll-004.jpg]]<br/>
  
== パッケージの取得とインストール ==
+
=== プロジェクトの依存関係の設定 ===
パッケージを取得してインストールしていきます。
+
コピーするにもちゃんとリコンパイルされた資源をコピーしないといけないので、プロジェクトの依存関係を設定することで、ビルドの順番を設定するよ。<Br/>
 +
ソリューションエクスプローラーからC♯のプロジェクトを右クリックして「ビルド依存関係」→「プロジェクト依存関係」を選択してね。<br/>
 +
「依存関係」タブの依存先にC++のプロジェクトが表示されているはずだから、チェックを入れてOKボタンをクリックしてね。
  
=== お約束 ===
+
== C♯のコード ==
Debian周りの最新化を行います。<br/><syntaxhighlight lang="bash">sudo apt-get update
+
MVVMモデルでサンプルを作ったからビューモデルが入っているけど…DLLを呼ぶには必要ないから無視してね。
sudo apt-get upgrade
+
=== モデル ===
sudo apt-get dist-upgrade</syntaxhighlight>
+
<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;
  
=== 「nautilus-dropbox」のインストール ===
+
//追加
「apt-get」コマンドで「nautilus-dropbox」をインストールします。<br/><syntaxhighlight lang="bash">sudo apt-get install nautilus-dropbox</syntaxhighlight><br/>すると…以下の様に確認が来ます。<syntaxhighlight lang="text">パッケージリストを読み込んでいます... 完了
+
using System.Runtime.InteropServices;
依存関係ツリーを作成しています               
 
状態情報を読み取っています... 完了
 
以下の追加パッケージがインストールされます:
 
  libappindicator1 libdbusmenu-glib4 libdbusmenu-gtk4 libindicator7 python-gpgme
 
以下のパッケージが新たにインストールされます:
 
  libappindicator1 libdbusmenu-glib4 libdbusmenu-gtk4 libindicator7 nautilus-dropbox python-gpgme
 
アップグレード: 0 個、新規インストール: 6 個、削除: 0 個、保留: 0 個。
 
422 kB のアーカイブを取得する必要があります。
 
この操作後に追加で 966 kB のディスク容量が消費されます。
 
続行しますか? [Y/n] </syntaxhighlight>問題なければ「y」キーを押してください。以下の様にだぁ~っとインストールが開始されます。<syntaxhighlight lang="text">取得:1 http://ftp.jp.debian.org/debian stretch/main amd64 libdbusmenu-glib4 amd64 12.10.2-2 [104 kB]
 
取得:2 http://ftp.jp.debian.org/debian stretch/main amd64 libdbusmenu-gtk4 amd64 12.10.2-2 [90.8 kB]
 
取得:3 http://ftp.jp.debian.org/debian stretch/main amd64 libindicator7 amd64 0.5.0-3+b1 [52.9 kB]
 
取得:4 http://ftp.jp.debian.org/debian stretch/main amd64 libappindicator1 amd64 0.4.92-4 [52.5 kB]
 
  
 +
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>
 +
        [DllImport("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);
  
hicolor-icon-theme (0.15-1) のトリガを処理しています ...
+
            //計算結果の表示
libdbusmenu-gtk4:amd64 (12.10.2-2) を設定しています ...
+
            MessageBox.Show("計算結果:" + l_Result.ToString());
libappindicator1:amd64 (0.4.92-4) を設定しています ...
+
        }
libc-bin (2.24-11+deb9u4) のトリガを処理しています ...</syntaxhighlight>
+
    }
 +
}
 +
</syntaxhighlight>
  
これで、「nautilus-dropbox」のインストール完了です。
+
=== ビュー ===
 +
<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;
  
== 「Dropbox」のダウンロードと初期設定 ==
+
//追加
# デスクトップからログインして「アクティビティ」から「ドロップボックス」を起動します。<br/>[[ファイル:Debian-dropbox-001.png | 400px]]<br/><br/>
+
using System.ComponentModel;
# 起動すると、何やら(というか、「Dropboxのアカウントが必要なので登録してね」って内容の)ダイアログが出ますが、サクッと「OK」を押します。<br/>[[ファイル:Debian-dropbox-002.png | 400px]]<br/><br/>
 
# するってぇと、「Dropbox」のダウンロードが始まります。<br/>[[ファイル:Debian-dropbox-003.png | 400px]]<br/><br/>
 
# ダウンロードが完了すると、引き続きインストールをします。<br/>[[ファイル:Debian-dropbox-004.png | 400px]]<br/><br/>
 
# インストールが完了すると、ブラウザが開いて「Dropboxのログイン画面」が表示されます。<br/>登録済みの、ユーザーIDとパスワードを入力してログインします。<br/>[[ファイル:Debian-dropbox-005.png | 400px]]<br/><br/>
 
# ログインすると以下の様な画面が表示されます。<br/>このままWEB版のDropboxを利用する場合は「Dropboxを続行する」をクリックすれば画面が遷移します。<br/>アカウントの紐付けだけなら、特に何もする必要はありません。<br/>しばらくすると「ファイル(nautilus)」が起動します。<br/>[[ファイル:Debian-dropbox-006.png | 400px]]<br/><br/>
 
# 認証が完了したら、ドロップボックスが同期を始めます。<br/>GNOME3の場合、アイコンは画面左下に表示されます。<br/>(下の画面では同期のマークが出ていませんが、PCと同じくちゃんと表示されます)<br/>[[ファイル:Debian-dropbox-007.png | 400px]]<br/>(追記:同期が完了すると、同期マークは消えるみたいです)<br/><br/>
 
  
= CUIインストール =
+
namespace CSharpToCDLL
CUIと言ってもデスクトップ環境がない状態でインストールを試みたのですが…どうやら、ver74.4.115はデスクトップ環境が必須のようですね。<br/>色々試しましたがダメでした。<br/>試したことを上げておきます。
+
{
 +
    class MainWindowViewModel : INotifyPropertyChanged
 +
    {
 +
        /// <summary>
 +
        /// ラベル表示用変数
 +
        /// </summary>
 +
        private String m_Label_Content;
  
# 普通に「[https://www.dropbox.com/ja/install-linux インストール - Dropbox]」にかかれている通りにインストール。<br/>「~/.dropbox-dist/dropboxd」コマンド実行時に途中で止まってしまいます。<br/>ちなみに「dropbox start」や「dropbox start -i」でも同じところで止まってしまいます。<br/><br/>
+
        /// <summary>
# 「nautilus-dropbox」をインストール<br/>上と同様に、「~/.dropbox-dist/dropboxd」コマンド実行時に途中で止まってしまいます。<br/>「dropbox start」や「dropbox start -i」だと動いているように(「Done!」で終わります)見えますが、アカウントとの連携メッセージが表示されませんでした。<br/>「dropbox status」で確認すると、ずっと「接続中…」のままになります。<br/><br/>
+
        /// ラベル表示文字列
# 「source.list」に無理やりDropboxのリポジトリを追加してインストール<br/>「nautilus-dropbox」と同じ現象になりました。<br/><br/>
+
        /// </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>
サービスを起動しているんだけど、どこでどうやって起動しているのか探していて、やっと発見しました。<br/>
+
        /// プロパティ変更通知
GNOMEのauto startを使用していました。<br/>
+
        /// </summary>
具体的には「~/.config/autostart」ディレクトリの「dropbox.desktop」というファイルです。<br/>
+
        /// <param name="p_PropertyName">プロパティ名</param>
中身は以下のようになっています。
+
        public void OnPropertyChanged(String p_PropertyName)
<syntaxhighlight lang="text">[Desktop Entry]
+
        {
Name=Dropbox
+
            if (this.PropertyChanged != null)
GenericName=File Synchronizer
+
            {
Comment=Sync your files across computers and to the web
+
                this.PropertyChanged(this, new PropertyChangedEventArgs(p_PropertyName));
Exec=dropbox start -i
+
            }
Terminal=false
+
        }
Type=Application
+
    }
Icon=dropbox
+
}
Categories=Network;FileTransfer;
+
</source>
StartupNotify=false</syntaxhighlight>
 
「dropboxd」ではなく「dropbox start -i」で起動しているんですね…。<br/>
 
(結局は一緒って話もありますが…)<br/>
 
これがわかれば「systemd」に変更することでユーザーを変更することもできそうです。
 
  
= 蛇足? =
+
[[Category:C♯]]
* Dropboxのデフォルトの同期先は「~/Dropbox」です
+
[[Category:C++]]
* Dropboxはログインと同時に同期を開始します。(ココらへんはPCと同じです)<br/>もし、起動と同時に同期を開始したい場合は「自動ログイン」にする必要があります。<br/>(CUIで起動する場合はユーザーの指定が必要??? - 何時か試したいです)
+
[[Category:dll]]
* 外付けのHDD(ext4もOKです)にも同期できますが、sambaのような共有ディレクトリには同期できません。
 
 
 
= 参考サイト =
 
[https://www.garunimo.com/program/linux/_etc_apt_sources_list.php /etc/apt/sources.list(パッケージのダウンロード元設定ファイル・Debian)]
 
 
 
[[Category:Debian]]
 
[[Category:Dropbox]]
 

2019年7月26日 (金) 16:46時点における版

久しぶりにやったら、すっかり忘れていたので覚書…

C++のDLLプロジェクト作成

まず、C++のDLLを作成するときの注意点… 作成するプロジェクトは、「Win32プロジェクト」を選択するんだ。
CShapeToCppDll-005.jpg


あと…アプリケーションの設定では「DLL」と「空のプロジェクト」を選択してね。
CShapeToCppDll-001.jpg


空のプロジェクトが作成されたら「cpp」「h」「def」ファイルを追加するんだ。今回は「CppDll.cpp」「CppDll.h」「CppDll.def」を追加したよ。


そしたら、プロジェクトのプロパティを開いて「構成プロパティ→リンカー→入力→モジュール定義ファイル」に「CppDll.def」を設定するんだ。
(DebugとReleaseでそれぞれ設定する必要があるんだよ。)
CShapeToCppDll-002.jpg

DLLのコード

ヘッダーファイル(*.h)

#ifndef DLLAPI
#define DLLAPI extern "C" __declspec(dllimport)
#endif

DLLAPI long __stdcall _Sum(const long p_Number1, const long p_Number2);

コードファイル(*.cpp)

#define DLLAPI

#include "CppDll.h"

DLLAPI long __stdcall _Sum(const long p_Number1, const long p_Number2)
{
	return p_Number1 + p_Number2;
}

モジュール定義ファイル(*.def)

LIBRARY	CppDll

EXPORTS
	_Sum

C♯のプロジェクト作成

ほとんどそのまま作るんだけど…ソリューションのコンパイル対策をしておくよ。

ビルドイベントの設定

C++のDLLはソリューションフォルダ直下の「Debug」や「Release」フォルダにDLLが格納されてしまうんだ。そうすると、デバッグするときにDLLが見つからないので、ビルドイベントを使ってコピーしてしまうよ。以下のように設定してね。(「Release」コンパイルするまでは「Release」フォルダがないのでコメントアウトしているよ)
CShapeToCppDll-004.jpg

プロジェクトの依存関係の設定

コピーするにもちゃんとリコンパイルされた資源をコピーしないといけないので、プロジェクトの依存関係を設定することで、ビルドの順番を設定するよ。
ソリューションエクスプローラーからC♯のプロジェクトを右クリックして「ビルド依存関係」→「プロジェクト依存関係」を選択してね。
「依存関係」タブの依存先にC++のプロジェクトが表示されているはずだから、チェックを入れてOKボタンをクリックしてね。

C♯のコード

MVVMモデルでサンプルを作ったからビューモデルが入っているけど…DLLを呼ぶには必要ないから無視してね。

モデル

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>
        [DllImport("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());
        }
    }
}

ビュー

<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>

ビューモデル

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

//追加
using System.ComponentModel;

namespace CSharpToCDLL
{
    class MainWindowViewModel : 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));
            }
        }
    }
}