名古屋スタジオでクライアントエンジニアをしている藤澤と申します。
ぼくは普段C++でアプリ開発をしているのですが、以前アプリのコードを流用してちょっとしたツールを作る必要が生じました。その際Visual Studio for Macを使おうと考えたのですが、Windows版の Visual Studioと違いMac版ではC++を使うことができずちょっと困ったので、今回はそのときのことを書いてみたいと思います。
作りたいツールの要件
- DBに登録されているデータがアプリで使用できるフォーマットになっているかチェックする。
- フォーマットのチェックにはアプリのコード(C++)を流用する。
- DBはMySQLで、SSH経由で接続する必要がある。
ツールの概要
- DBの接続はC#でSSH.NETとMySQL Connector/NETを利用。
- C++部分はXcodeでFrameworkを作成し、C#からInteropServicesを利用して読み込む。
なお、前者については調べればたくさん情報が出てくると思いますので割愛し、今回は後者について記載したいと思います。
環境
- Xcode 13.0
- Visual Studio for Mac 8.10.6
実装
Frameworkの作成
まずはXcodeでFrameworkを作成します。
データのチェック処理として以下のようなクラスがあるとします。
class Validator
{
public:
Validator(std::string value);
std::vector<std::string> getErrors();
};
このクラスをC#側から呼び出すための関数を用意します。
(ファイル名はなんでもよいです)
extern "C" {
void validate(const char *text, char *result);
}
extern "C" void validate(const char *text, char *result)
{
auto value = Validator(text);
std::string errors;
for (int i = 0; i < value.getErrors().size(); i++)
errors += value.getErrors().at(i) + (i == value.getErrors().size() - 1 ? "" : "\n");
strcpy(result, errors.c_str());
}
チェック対象の文字列をtext
で受け取り、チェック結果をresult
で返すようにしています。
呼び出し側の実装
続いてツールのフロントエンド部分をVisual Studioで作成します。
まずは「ネイティブ参照の追加」で先ほど作成したFrameworkを追加します。
次にvalidate
関数を呼び出すためのメソッドをViewController.cs
に定義します。
using System;
using System.Runtime.InteropServices;
using System.Text;
using AppKit;
using Foundation;
namespace SampleApp
{
public partial class ViewController : NSViewController
{
[DllImport("SampleLib.framework/SampleLib", EntryPoint = "validate")]
static extern void validate(string text, StringBuilder result);
// (省略)
}
}
DllImport
属性でFrameworkのファイル名と呼び出す関数名を指定し、メソッドのシグネチャはC++側の定義と一致させます(string
がconst char*
に、StringBuilder
がchar*
に対応します。型の対応はこちらが参考になるかと思います)
あとは通常のC#のメソッド同様に利用することができます。
var result = new StringBuilder(4096);
validate(this.Input.Value, result);
this.Output.Value = result.ToString();
おわりに
今回の内容は以上です。今回記載した方法を使えば、macOS用に配布されているライブラリをVisual Studioから利用することも可能ですので、いろいろできることが増えそうな気がします。何かしらのお役に立てば幸いです。