備忘録

備忘録

C#でProtocolBuffersを使う方法

Ⅰ. はじめに

タイトルの通り「C#でProtocolBuffersを使う方法」です。
本記事ではproto3(ProtocolBuffers version 3)を対象とします。

また、protoファイルを書く時は VisualStudio Codeに vscode-proto3 をインストールして開発する事をおすすめします。

また、ProtocolBuffersをリバースする方法はこちら
https://kagasu.hatenablog.com/entry/2017/03/17/124259

Ⅱ. やり方(Google.Protobufを使う方法)

1. NuGetから Google.Protobuf をインストールする
Install-Package Google.Protobuf
2. protoファイルを作成する

Human.proto

syntax = "proto3";
package MyPackage;

message Human {
  string name = 1;
  uint32 age = 2;
}
3. protoc.exe をダウンロードする

https://github.com/google/protobuf/releases

4. protoファイルからC#のクラスを自動生成する
protoc.exe --csharp_out=../ProtoModel Human.proto
5. サンプルプログラムを書く
using Google.Protobuf;
using MyPackage;

static void Main(string[] args)
{
  var human = new Human
  {
    Name = "name001",
    Age = 20
  };

  byte[] bytes = human.ToByteArray();

  Console.WriteLine(BitConverter.ToString(bytes));

  // デシリアライズ
  // human = Human.Parser.ParseFrom(bytes);
}
実行結果

f:id:kagasu:20180429232357p:plain

Ⅲ. やり方(protobuf-netを使う方法)

1. NuGetから protobuf-net をインストールする
Install-Package protobuf-net
2. protoファイルを作成する

Human.proto

syntax = "proto3";
package MyPackage;

message Human {
  string name = 1;
  uint32 age = 2;
}
3. protogen.exe をダウンロードする

https://github.com/mgravell/protobuf-net/releases

4. protoファイルからC#のクラスを自動生成する
protogen.exe --csharp_out=../ProtoModel Human.proto
5. サンプルプログラムを書く
using ProtoBuf;
using MyPackage;

static void Main(string[] args)
{
  var human = new Human
  {
    Name = "name001",
    Age = 20
  };

  using (var ms = new MemoryStream())
  {
    Serializer.Serialize(ms, human);
    byte[] bytes = ms.ToArray();
    Console.WriteLine(BitConverter.ToString(bytes));

    // デシリアライズ
    // human = Serializer.Deserialize<Human>(ms);
  }
}
実行結果

f:id:kagasu:20180429232357p:plain

Ⅳ. Google.Protobuf (protoc.exe)と protobuf-net (protogen.exe) の違い

1. enumの場合

enum QueryType {
  QUERYTYPE_NONE = 0;
  QUERYTYPE_ALL = 1;
}
Google.Protobuf (protoc.exe)

protoc.exe は C#用に最適化されたC#コードを出力します。
以下のようにC#で書くことができます。

var queryType = QueryType.All;
protobuf-net (protogen.exe)

protogen.exe は愚直に(最適化されていない)C#コードを出力します。
以下のようにC#で書くことができます。

var queryType = QueryType.QuerytypeAll;

Canvasで画像を重ね合わせる方法

Ⅰ. はじめに

タイトルの通り「Canvasで画像を重ね合わせる方法」です。

Ⅱ. サンプルプログラム

index.html
<!DOCTYPE html>
<html>
  <body>
    <canvas id="my-canvas" width=300 height=300></canvas>
    <script src="index.js"></script>
  </body>
</html>
index.js
// 優先度が低い順に画像パスを指定する。(上に表示したい画像は後ろに指定する)
const imgs = ['img/character.png', 'img/frame.png', 'img/rarity.png'];
const context = document.getElementById('my-canvas').getContext('2d');

const loadImage = url => {
  return new Promise((resolve) => {
    const img = new Image();
    img.onload = () => resolve(img);
    img.src = url;
  });
};

Promise.all(imgs.map(loadImage)).then(imgs => {
  imgs.forEach(img => {
    context.drawImage(img, 0, 0, 300, 300);
  });
});
画像
character.png frame.png rarity.png

実行結果

f:id:kagasu:20180428113058p:plain

C#でLuaを使う方法(NLuaの使い方)

Ⅰ. はじめに

タイトルの通り「C#Luaを使う方法(NLuaの使い方)」です。

Ⅱ. やり方

1. NuGetからNLuaをインストールする
Install-Package NLua
2. サンプルプログラム

humans.lua

Humans = {
  [10001] = {id = 10001, name = 'name001' },
  [10002] = {id = 10002, name = 'name002' },
  [10003] = {id = 10003, name = 'name003' }
}

Program.cs

using NLua;
using System;

namespace LuaTest
{
  class Program
  {
    static void Main(string[] args)
    {
      using (var lua = new Lua())
      {
        lua.DoFile("humans.lua");
        var humans = (LuaTable)lua["Humans"];
        foreach (var key in humans.Keys)
        {
          var human = (LuaTable)humans[key];
          Console.WriteLine($"{human["id"]}, {human["name"]}");
        }
      }
    }
  }
}

実行結果

f:id:kagasu:20180424220523p:plain

Vue+webpackでlodashを使う方法

Ⅰ. はじめに

タイトルの通り「Vue+webpackでlodashを使う方法」です。

Ⅱ. やり方

1. lodashをインストールする
npm install lodash
2. src/main.js に 以下をコピペする
import lodash from 'lodash'
Object.defineProperty(Vue.prototype, '$lodash', { value: lodash })
3. lodashを使う
let accounts = [ /* 省略 */ ]
this.$lodash.orderBy(accounts, ['id', 'name'], ['asc', 'asc'])

C#でWinPcapを使う方法(SharpPcapの使い方)

Ⅰ. はじめに

タイトルの通り「C#WinPcapを使う方法(SharpPcapの使い方)」です。
WinPcapを利用したキャプチャを行う為、レイヤ2(データリンク層)レベルでのキャプチャが可能です。

予めWinPcapをインストールする必要があります。
https://www.winpcap.org/default.htm

Ⅱ. やり方

1. NuGetからSharpPcapをインストールする
Install-Package SharpPcap

# .NET Core版
Install-Package SharpPcap.Core
2. サンプルプログラムをコピペする
// https://github.com/chmorgan/sharppcap/blob/master/Examples/Example3.BasicCap/Example3.BasicCap.cs
using SharpPcap;
using SharpPcap.AirPcap;
using SharpPcap.LibPcap;
using SharpPcap.WinPcap;
using System;
using System.Linq;

namespace WinPcapTest
{
  class Program
  {
    public static void Main(string[] args)
    {
      var devices = CaptureDeviceList.Instance;

      if (devices.Count < 1)
      {
        Console.WriteLine("デバイスが見つかりませんでした。");
        return;
      }

      foreach (var dev in devices.Select((val, i) => new { val, i }))
      {
        Console.WriteLine($"({dev.i}) {dev.val.Name} {dev.val.Description}");
      }

      Console.Write("キャプチャ対象のデバイスを選択して下さい: ");
      var deviceIndex = int.Parse(Console.ReadLine());
      var device = devices[deviceIndex];

      device.OnPacketArrival += Device_OnPacketArrival;

      int readTimeoutMilliseconds = 1000;
      switch (device)
      {
        case AirPcapDevice airPcap:
          // NOTE: AirPcap devices cannot disable local capture
          airPcap.Open(OpenFlags.DataTransferUdp, readTimeoutMilliseconds);
          break;
        case WinPcapDevice winPcap:
          winPcap.Open(OpenFlags.DataTransferUdp | OpenFlags.NoCaptureLocal, readTimeoutMilliseconds);
          break;
        case LibPcapLiveDevice livePcapDevice:
          livePcapDevice.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);
          break;
        default:
          throw new InvalidOperationException($"unknown device type of {device.GetType().ToString()}");
      }

      device.StartCapture();
      Console.ReadLine();
      device.StopCapture();
      device.Close();
    }

    private static void Device_OnPacketArrival(object sender, CaptureEventArgs e)
    {
      var time = e.Packet.Timeval.Date;
      var length = e.Packet.Data.Length;
      Console.WriteLine($"{time.Hour}:{time.Minute}:{time.Second},{time.Millisecond} Len={length}");
      Console.WriteLine(BitConverter.ToString(e.Packet.Data));
    }
  }
}
実行結果

f:id:kagasu:20180419182408p:plain