びわの家ブログ

Unity向けdll作成及びC言語メモ

この記録について

前職の仕事でc言語でダイナミックライブラリを作成してUnityで使いながらデバッグするということをしていたメモを掘り起こしたもの。

dll関連

dll作る方法

https://littlewing.hatenablog.com/entry/2018/01/18/150359

dllMain関数について
dllからはmain関数は呼ばれず、代わりに
dllMainという関数がwindow.hに用意されているらしい。
今回は使わなかったが参考程度に

https://ameblo.jp/zrfcsctd/entry-10790648253.html

unity起動中のdll更新

dll側のログを出す方法
使わなかったけどこんな方法あるらしいメモ

http://cammy.co.jp/technical/2016/04/29/windows-guiプログラムでデバッグ情報をコンソールを表示/

c#でstringのメモリを保持して、dll経由でcで書き込む(stringを返す関数をつくる)
このページの文字列を受け取る場合ってところをみる

https://araramistudio.jimdo.com/2018/05/09/c-からc-のdllを呼び出す/

出力側の関数例

void hoge(char* str, int strlen){
    sprintf_s(str, strlen, "Hello %s\n", "World");
}

dotnet > 4. からStringBuilderにClear関数ができた(らしい)ので積極的に使いたい

https://dobon.net/vb/dotnet/string/stringbuilderclear.html

cからunity(c#)のコードを呼び出す

http://tips.hecomi.com/entry/2016/01/05/230405

vsでビルドするたびにビルド日時を書きだす
何がしたいか
ビルド前に任意のソースコードを生成したい。
まさにこんな感じの

#define BUILD_DATE 20190117140034 

(日付をYYYYMMDDhhmmss形式にしたものを新しくしたい)
何のために
dllを開発してるとこれいつビルドしたやつだっけみたいになって
これほんとに新しいdllかどうか不安になりみたいなことがあったので
dll側に

__declspec( dllexport ) int CheckVersion(){
    return BUILD_DATE //ビルド日時
}

とか書いてあげればdllを使う側からバージョンがチェックできる気がした。
どうやってやるの
結論

  • slnがあるディレクトリにdate.batとかつくる
  • date.bat echo #define BUILD_DATE "%date% %time%" > date.c
  • vsでプロパティ > ビルドイベント > ビルド前のイベントひらく
  • call $(SolutionDir)date.bat
  • 任意のところで#include "date.c"としてBUILD_DATEを使う

何してるか

  • ビルドした時の時間でファイルを更新したいのでビルド前のイベントを使う
  • ここでファイルを書き換えてからビルドすればいいはず
  • echoで日付をYYYYMMDDhhmmssにフォーマットして#defineとかつけたりして
  • '>' でファイルに上書き出力すればいい
  • batファイルにする
  • batファイルをたたくのをビルドイベントに設定する

はまったポイント

  • ビルドイベントにecho書いたらvsの出力に出力されるだけでファイルつくられない。。
  • 使わなかったけどビルドイベントの%のエスケープは%25
  • batファイルはcallをつけて実行する
  • batが実行されるフォルダは$(ProjectDir)なのでbatで出力するディレクトリに注意
  • ディレクトリ間違えるとエラーになる

c言語関連

メモリコピー

  • memcpyって関数があるらしいよ https://bituse.info/c_func/56
  • 複製というよりもメモリの中の値を別のメモリにコピーって感じだった
  • なので確保してないメモリに使おうとすると止まる

スレッドと排他処理
メインスレッド上でforループで永続化するとdll呼び出したときにunityとまる。
スレッド分けましょう

https://paveway.hatenablog.com/entry/2018/12/14/win32api_criticalsection

マルチスレッドはCreateThreadを使ったが_beginthreadx使ったほうが安全らしい。
http://www.geocities.jp/debu0510/personal/kusosure.html
安全してて変えるの怖かったからそのままCreateThreadつかったが。。
構造体
なんとc言語の構造体はtypedef使わないと毎回構造体名の前に"struct"と書かないといけないです。
書くのが普通なんだけど省略のために書くのが普通っぽいですよ
https://www.cc.kyoto-su.ac.jp/~yamada/programming/struct.html
メモリリーク検出
メモリリーク怖い。恐ろしい。
終了時に検出する方法がある

https://hwada.hatenablog.com/entry/20080304/1204609100

ただ、visual studioの停止ボタンなどで停止すると検出されないので、
適当なタイミングでexit()よんでテストしてみよう!精神的に安心。
あとは地道にコマンドプロンプトで
tasklist /v /fi "imagename eq zForceCalibration.exe"
とかたたいてメモリ使用量が増えていかないかみたりしていた。
テキスト関連
sprintf
visual studioだとsprintfが使えなくて代わりにsprintf_sを使うことになる。
charに文字のサイズ指定して変数をformatして入れてくれる。
printfのラッパー関数つくる
可変引数をもつ関数

https://qiita.com/kurasho/items/1f6e04ab98d70b582ab7

入出力関数
http://rainbow.pc.uec.ac.jp/edu/program/b1/Ex7-2.htm