差分

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

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

1,537 バイト追加, 2019年7月26日 (金) 16:46
さくらのレンタルサーバーで最新のMediaWikiを使用していることが前提なんだけど…<br/>「SyntaxHighlight」を使用すると、「構文ハイライトエラー」になってしまう…。久しぶりにやったら、すっかり忘れていたので覚書…
== C++のDLLプロジェクト作成 ==
まず、C++のDLLを作成するときの注意点…
作成するプロジェクトは、「Win32プロジェクト」を選択するんだ。<br/>
[[ファイル:CShapeToCppDll-005.jpg]]
原因は単純でさくらのレンタルサーバーのPythonは現時点で2.7…SyntaxHighlightはPython3が前提…<br/>
当然うまく動かないわけです…。
あと…アプリケーションの設定では「DLL」と「空のプロジェクト」を選択してね。<br/>
[[ファイル:CShapeToCppDll-001.jpg]]<br/>
そこで、ホームディレクトリにPython3を入れて、そちらを参照するようにSyntaxHighlightを書き換えちゃいます。
= Python3のインストール =参考サイトに基づいて、Pythonの最新版(Python3)をインストールしていきます。<br/>先ずはホームディレクトリに作業用のディレクトリを作成して移動します。<syntaxhighlight lang="bash">mkdir ~/workcd work</syntaxhighlight>空のプロジェクトが作成されたら「cpp」「h」「def」ファイルを追加するんだ。今回は「CppDll.cpp」「CppDll.h」「CppDll.def」を追加したよ。
次に、wgetコマンドでPythonの公式サイトからモジュールをダウンロードします。そしたら、プロジェクトのプロパティを開いて「構成プロパティ→リンカー→入力→モジュール定義ファイル」に「CppDll.def」を設定するんだ。<br/>(DebugとReleaseでそれぞれ設定する必要があるんだよ。)<syntaxhighlight lang="bash"br/>wget https[[ファイル://www.python.org/ftp/python/3.7.4/PythonCShapeToCppDll-3002.7.4.tar.xzjpg]]<br/syntaxhighlight>(ダウンロードパスは適宜見直してください)
== DLLのコード ==
=== ヘッダーファイル(*.h) ===
<syntaxhighlight lang="cpp">
#ifndef DLLAPI
#define DLLAPI extern "C" __declspec(dllimport)
#endif
ダウンロードしたらtarコマンドで解凍します。DLLAPI long __stdcall _Sum(const long p_Number1, const long p_Number2);<syntaxhighlight lang="bash">tar -xzf Python-3.7.4.tar.xz</syntaxhighlight>
=== コードファイル(*.cpp) ===
<syntaxhighlight lang="cpp">
#define DLLAPI
解凍すると「Python-3#include "CppDll.7.4」ディレクトリが作成されますので、そこに移動します。<syntaxhighlight lang=h"bash">cd Python-3.7.4</syntaxhighlight>
DLLAPI long __stdcall _Sum(const long p_Number1, const long p_Number2)
{
return p_Number1 + p_Number2;
}
</syntaxhighlight>
以下のコマンドでインストール先を変更します。=== モジュール定義ファイル(*.def) ===<syntaxhighlight lang="bashtext">./configure --prefix=$HOME/local/python/</syntaxhighlight>LIBRARY CppDll
EXPORTS
_Sum
</syntaxhighlight>
そしたらmakeしてインストールします。<syntaxhighlight lang="bash">make= C♯のプロジェクト作成 ==make install</syntaxhighlight>ほとんどそのまま作るんだけど…ソリューションのコンパイル対策をしておくよ。
=== ビルドイベントの設定 ===
C++のDLLはソリューションフォルダ直下の「Debug」や「Release」フォルダにDLLが格納されてしまうんだ。そうすると、デバッグするときにDLLが見つからないので、ビルドイベントを使ってコピーしてしまうよ。以下のように設定してね。(「Release」コンパイルするまでは「Release」フォルダがないのでコメントアウトしているよ)<br/>
[[ファイル:CShapeToCppDll-004.jpg]]<br/>
インストールに使用したディレクトリは削除しちゃいます。=== プロジェクトの依存関係の設定 ===コピーするにもちゃんとリコンパイルされた資源をコピーしないといけないので、プロジェクトの依存関係を設定することで、ビルドの順番を設定するよ。<syntaxhighlight lang="bash"Br/>cd ~rm -fr workソリューションエクスプローラーからC♯のプロジェクトを右クリックして「ビルド依存関係」→「プロジェクト依存関係」を選択してね。<br/syntaxhighlight>「依存関係」タブの依存先にC++のプロジェクトが表示されているはずだから、チェックを入れてOKボタンをクリックしてね。
= SyntaxHighlightの編集 =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{ /// <brsummary> /// MainWindow.xaml の相互作用ロジック /// </summary>ターゲットは「create_pygmentize_bundle」ファイルです。 public partial class MainWindow : Window { /// <summary> /// DLLの関数定義 /// <syntaxhighlight lang/summary> /// <param name="p_Number1">数値1</param> /// <param name="bashp_Number2">cd [MdiaWikiのディレクトリ]数値2</param> /extensions/SyntaxHighlight_GeSHi/pygments<returns>合計</syntaxhighlightreturns>[MdiaWikiのディレクトリ]は自分の環境に合わせて書き換えてください。 [DllImport("CppDll.dll")] private extern static Int32 _Sum(Int32 p_Number1,Int32 p_Number2);
/// <summary>
/// 標準のコンストラクタ
/// </summary>
public MainWindow()
{
InitializeComponent();
}
バックアップを作成します。 /// <summary> /// ボタンクリックイベントハンドラ /// </summary> /// <syntaxhighlight langparam name="bashsender">cp create_pygmentize_bundle create_pygmentize_bundle_bkイベント送信元</param>mv pygmentize pygmentize_bk /// <param name="e">イベント情報</syntaxhighlightparam>(「pygmentize」ファイルは作成し直すので、mvしています) private void Button_Click(object sender, RoutedEventArgs e) { //DLLの関数を呼び出す Int32 l_Result = _Sum(300, 500);
//計算結果の表示
MessageBox.Show("計算結果:" + l_Result.ToString());
}
}
}
</syntaxhighlight>
「create_pygmentize_bundle」ファイルを修正します。=== ビュー ===<brsource 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> <syntaxhighlight langGrid.RowDefinitions> <RowDefinition Height="python5" line highlight/> <RowDefinition Height="1,19,6024"/>#! <RowDefinition/home> <RowDefinition Height="5"/[userid]> </localGrid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="5"/python> <ColumnDefinition/bin> <ColumnDefinition Width="5"/python3># -*- coding: utf-8 -*- <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; Create a standalone, executable 'pygmentize' bundleusing System.Text; Author: Ori Livnehusing System.Threading.Tasks;
"""//追加import hashlibimport ioimport osimport statimport textwrapimport urllib.requestimport xmlrpcusing System.clientimport zipfileComponentModel;
namespace CSharpToCDLL
{
class MainWindowViewModel : INotifyPropertyChanged
{
/// <summary>
/// ラベル表示用変数
/// </summary>
private String m_Label_Content;
PYGMENTIZE_LAUNCHER = textwrap.dedent('''\ /// <summary> #! /home/[userid]/localラベル表示文字列 /python/bin/python3</summary> public String Label_Content { set { this.m_Label_Content = value; this.OnPropertyChanged("Label_Content"); } get { return this.m_Label_Content; } }
import sys /// <summary> import pygments.cmdline /// プロパティ変更イベントハンドラ try: /// </summary> sys.exit(pygments.cmdline.main(sys.argv)) except KeyboardInterrupt: sys.exit(1)''') 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>
print('Querying PyPI for the latest Pygments release...')pypi = xmlrpc.client.ServerProxy('https://pypi.python.org/pypi')latest_version = pypi.package_releases('Pygments')[0]url = Nonefor release in pypi.release_urls('Pygments', latest_version): if (release['packagetype'] == 'bdist_wheel' and release['python_version'].startswith('py2')): url = release['url'] md5_digest = release['md5_digest'] break if not url: raise RuntimeError('No suitable package found.') print('Retrieving version %s (%s)...' % (latest_version, url))req = urllib.request.urlopen(url)buf = io.BytesIO(req.read()) print('Verifying...')if hashlib.md5(buf.getvalue()).hexdigest() != md5_digest: raise RuntimeError('MD5 checksum mismatch.') print('Creating executable ZIP bundle...')with zipfile.ZipFile(buf, 'a') as zf: zf.writestr('__main__.py', PYGMENTIZE_LAUNCHER) data = buf.getvalue()script_dir = os.path.dirname(os.path.abspath(__file__))file_path = os.path.join(script_dir, 'pygmentize')with open(file_path, 'wb') as f: f.write(b'#!/home/[userid]/local/python/bin/python3\n') f.write(data) file_st = os.stat(file_path)os.chmod(file_path, file_st.st_mode | stat.S_IEXEC) with open(os.path.join(script_dir, 'VERSION'), 'w') as f: f.write(latest_version + '\n') print('Done. Wrote %s bytes to %s' % (len(data), file_path))</syntaxhighlight>([userid]は書き直してください)  最後に「pygmentize」を作成し直します。<syntaxhighlight lang="bash">/home/[userid]/local/python/bin/python3 ./create_pygmentize_bundle</syntaxhighlight>([userid]は書き直してください) = WEBブラウザのキャッシュ =WEBブラウザのキャッシュが残っていると、なかなか変わった感じがしないかもしれません。<br/>そんな時は例えば「<syntaxhighlight lang="bash">」を「<syntaxhighlight lang="bash" line>」などに書き直してみてください。<br/>これで、行番号が表示されればOKです。 = 参考サイト =[https://emptypage.jp/notes/pymods-on-sakura.html さくらのレンタルサーバで Python 外部モジュールを使う]<br/>[https://affitips.com/pages/65.html さくらにPython3をインストールしたときのメモ - アフィリエイト&ウェブ制作のtips] [[Category:さくらサーバーC♯]][[Category:MediaWiki]][[Category:Python3C++]][[Category:SyntaxHighlightdll]]

案内メニュー