echo("備忘録");

IT技術やプログラミング関連など、技術系の事を備忘録的にまとめています。

フリーになる時に必要な手続き

さて、一応本格的にフリーランスとしてスタートを切りました。(と言ってもまだ1週間なので、何とも言えませんが)
ただ今のところは、前みたいな人間関係のトラブルはなく、むしろ人間関係は良い感じです。

さて、僕も開業前には色々調べたり手続きをしましたが、フリーになる時に必要な手続きって何だろう?って思ったので、簡単にまとめてみました。
勘違いがあるかもしれませんが、参考程度に。


1.開業届の提出
まあ、まずはこれをしないと始まりません。
というか、とりあえずこれだけ提出しておけば、法律的にはフリー(というか、事業主)と認められます。

そうそう、「屋号」は無くても良いので「いい屋号が浮かばない…」っていう場合は、とりあえず屋号なしでもOKです。(ブランディングとか認知度のことを考えたら、あるに越したことはないですが。)
あと「業種」ですが、これ一つだけで個人事業税が課税されるかどうかや税率が変わるので、複数の業務を行う際は慎重に選択しましょう。(もちろん、ウソを付くのはダメですが。)

2.青色申告承認申請書の提出
フリーランス」でググると、大抵出てくる言葉ですよね。簡単に言えば「白色申告よりも詳細に申告するから、控除額(=非課税額)を65万円増やして下さい」という申請用紙です。
これ、始めは「記帳が大変そう…」とか「複式簿記って難しそう…」って思いましたが、実際にやり始めてみて分かりました。

これは絶対に申請した方がいいです。

いや、やってみて分かったんですが、複式簿記とか仕訳って、思ったほど難しくないです。
もちろん自営で店舗などを経営する人はすごい複雑なんでしょうが、僕のような常駐型フリーエンジニアの場合、基本的に

  • 収入…毎月の契約金
  • 支出(経費)…通勤代&車・ガソリン代

くらいで、あとはほとんど文房具とか技術関連の書籍とか、細々とした経費くらいでしょうし、それなら一度仕訳パターンを覚えてしまえば、1日10数分で記帳が完了すると思います。
それに最近は「freee」とか「MFクラウド確定申告」のような、安くて非常に便利な会計ソフトもたくさんありますので、知識が乏しくても何とかなるでしょうし、それで控除額が65万円増えるなら、絶対そのほうが良いと思います。

3.国民健康保険国民年金
会社員と違い、フリーだと会社の社会保険や厚生年金には入れないので、国民健康保険国民年金に加入することになります。(ただし退職後2年までなら前の会社のものに継続して加入出来ます。)

ただ、これが結構な額なんですよ…会社員って優遇されていたんだな、って実感します。(会社員は会社が半額負担してくれるから)
まあ一応、国民健康保険は「親などの扶養に入る」、国民年金は「減免申請をする」事で、減免される可能性はあります。
※ただ、普通は「開業する=満足に働ける」状態だと思うので、難しいとは思います。逆に病気や怪我などで「働き無くても働けない」人は、絶対に申請すべきだと思います。

…ちょっと長くなりそうなので、次回はまた後日。

フリーエンジニアになりました その2

また日付が空いてしまいました。すいません。

色々あって、なかなかパソコンに触れませんでした…

 

で、前回の続きなんですが、ニコニコ動画を見ていたら、こんな記事が。

news.nicovideo.jp

もちろん僕は学生ではないんですが、心当たりが無いわけではないんです。

実は闘病中、医師の勧めで発達障害とかアスペルガーに関する検査を受けたことはあるんですが、結果がかなり少数派というか、人とはかなり違っていて、それ以降、医師やカウンセラーの言葉に「個性だから」という言葉が明らかに増えたような気がします。(ただ僕の場合、コミュ障なんてことはなく、むしろ「よく喋るエンジニア」と言われることがほとんどですが…)

 

ただ、その「個性」ってのが理解されなくて、苦労した事は決して少なくないです。間違いなく求められた以上の成果を残しているのに、無理やり理由をつけて色々言われたり、最悪クビにされたり。

でも自分を認めてくれた会社では高い評価も頂いたし、自分も頑張れたので、これまで何とか会社員を続けてきたのですが、今回の件で完全に「会社は社員なんか守ってくれない」って思ったわけです。それで完全にフリーになる決心がつきました。「会社に依存する生き方は自分には無理だ!」って。

 

ただ先程「フリーになる決心」と書いたのですが、前回も書いた通り「フリーになってでも働いて食べていかなきゃいけない」のもまた事実なわけで。

こういう「(コミュ障など)病気や個性の件でうまく働けない」などのネットニュースを見ると大抵「だからニートなんだよ」とか「人生詰んだ」とか書いてあるけど、それは全くのお門違い。大変だろうし、つらいのも分かるけど、だからって「働かない理由」にはならないし、学齢期を過ぎた以上、普通は何かしら働いて収入を得ないといけないわけで(もちろん、医者が終了禁止するレベルの病気などは別として。)。

 

実際僕も生きづらさを感じてはいるけど、絶対そんな事は言いたくない。むしろ働き盛りの30代にほとんど働けなかった分を今から取り戻したい、という気持ちが非常に強い。間違いなく闘病中だった10年前より、気持ちはむしろ若いと思う。

でも、残念ながら、世間というのはそんなに甘くないし、病気が治ったからって「8年間の病気」の事がチャラになるわけじゃない。でも何とかして働いて食べていかないといけない。これは紛れもない現実。

じゃあどうするか、といったら「そんな事が関係ない方法で生きていけばいいだけじゃないか」という結果に至ったわけです。まあ、そうしないと食べていけないわけですし。「こち亀」の両さんの言葉を借りれば「生きるか死ぬかではなく、どう生きるか」ってやつです。

 

なんかフリーエンジニアになったってことを軽く書くつもりが、やけに重い内容になってしまいましたね…次はもっと軽い感じの事を書こうと思います。

フリーエンジニアになりました。その1

前回から、また期間が空いてしまいました…すいません。

前回の記事で会社を辞めたと書きましたが、新しい仕事探しやそれに伴う転居やらで、なかなか時間が取れませんでした。
で、新しい仕事ですが、いろいろ考えた結果、しばらくの間フリーエンジニアとしてやっていくことにしました。

ただ「フリーエンジニア」と言うと、ネット上ではよく「報酬が高い」とか「スキルを活かして起業して」とかよく書かれていますが、そのつもりは(今のところ)全くありません。
むしろ「そのほうが自分に合っている(自分には会社員は合わない)かも」という思いが強かったので、一旦フリーを経験するのも悪く無いかな、と思いまして。

というのも、前の会社の事は何回か書いたのですが、実はこれが初めてではなく、過去にも何回かあったんです。
「自分の事を理解してくれない(理解しようとしない)」とか、ちょっと個性的なだけで「異端児」「反組織的」扱いとか。

確かに僕は自分でも「個性的」とか「ちょっと人と考え方が変わってるかも…」という所があるのは認めていますが、それだけでそういう扱いされて、ロクな評価をされないというのは、ちょっとねえ。
(それに、自分を認めてくれた会社ではちゃんと結果を残し続けてきた、という確固たる実績と自負が自分にはありますから。)

あともう一つ、約10年のうつ病の経歴を理由に敬遠されることが、本当に多いです。
「スキル的には、ぜひ来て欲しいんですが…」とは言うんですが、悪い言い方をすれば「契約社員でなら雇ってやってもいいよ」みたいな、足元を見る会社の多いこと、多いこと。
「再チャレンジ」ってなんだったんだろうなあ…って感じです。

まあ、そんなことが本格的にうつ病を発症して以来、8年間近く続きまして、もちろん今後も続くと考えています。
そうなると、普通に考えたら、まともに働く事自体、困難で苦痛な訳です。
でもそんなこと言っても、働かない訳にはいかないし、そもそも働かないと食べて行けないわけです。
「働かざる者食うべからず」ですから。

それに、何だかんだ理由をつけて働こうとしないニートになんか絶対なりたくないですし、やっと普通に働けるようになった以上、まともに働けなかったこの約10年の分も働きたい、という思いがあります。
それになりより、何だかんだ言って、やっぱり自分はITエンジニアの仕事が天職だと思ってますから。

そう考えた時、「組織で働けないなら、フリーエンジニアとして働くのも、悪くないんじゃない?」って思ったんです。
本当、ITエンジニアで(手に職を付けてて)良かった、って思いました。

もちろん、実際はこんな軽いノリの話ではなく、むしろ「フリーエンジニアしか食べていく方法がないから」と言ったほう正解なのですが、
まあ、フリーになったのはこういう経緯があったからなのです。

この事については、もうちょっと書きたいので、次回に続きます。

JavaScriptで動的なバリデーション表示

オレは会社をやめたぞ!ジョジョーーッ!

という訳で、今まで色々書いてきた会社のことですが、とうとう辞めました。
今まで色々あったのですが、「こんな奴の下にずっといたら、絶対ダメになるな…」という決定的なことがあったので、案の定「辞めてもらってもいいんだよ」と言われた時に「はい、じゃあ辞めます。」って言いました。
向こうはまさか辞めるとは思ってなかったようですが、そんな事知ったことじゃないし、それにDirectXの件は要望通りのものは一通り完成させましたし(このブログでは、小出しにしてますけどね…)
C#VC++、両方分かる人が僕しかいない会社でしたが、あれはあの後どうなるんだろうな…


で、今週は訳あって、依頼された簡単な問い合わせシステムをPHPで作成してたのですが、今までWebシステムの入力検証って、定番通りサーバーで行ってエラー内容をヘッダとかに表示させてました。
ただ、最近は色々なWebサイトで見られる通り、クライアント側で行って動的にHTMLなどを作成して…というのが多いですよね。

例えば、
f:id:Makky12:20160826202128p:plain
エラーがない場合は、こんな感じなんですが、


f:id:Makky12:20160826202137p:plain
入力内容がエラーだと、HTMLなどを動的に作成して、こんな風にわかりやすく表示してくれるやつです。

もともと「どうやって作ってるんだろうな」と思っていましたが、いい機会だったので、自分で作ってみました。
(もっと良いやり方もあるのでしょうが、時間の関係もあり、とりあえず今回はこんな感じです。)

<!-- HTML側のコード(一部抜粋) -->
<tr>
    <th>
        お名前<span class="must">必須</span>
    </th>
    <td class="td" id="td_name">
        <input type="text" class="form-control" name="name" id="form_name"
        value="" maxlength="10" placeholder=" 例)山田 太郎" 
        onchange="validate('td_name', 'form_name');">
    </td>
</tr>|


// JavaScript側のコード
function validate(objTd, objId)
{
    var objCtrl = document.getElementById(objId);
    var objRegExp = null;
    var msg = "";

    switch(objId)
    {
        // 本当は他にもあるけど、今回は省略。
        case 'form_name':

            if("" == objCtrl.value) {
                msg = "お名前は必須です。";
            }else{
                if (objCtrl.value.length > 10) {
                    msg = "お名前は10文字以内で入力して下さい。";
                }else{

                    // 正規表現による文字チェック
                    objRegExp = new RegExp(/^[\sa-zA-Z0-9!#$%&=-~^@+.ぁ-んーァ-ヶー一-龠1-9A-Za-z!#$%&=-~^@+.、。?-]+$/);
                    if (!objRegExp.test(objCtrl.value)) {
                        msg = "お名前の値が不正です。";
                    }
                }
            }

            break;
    }

    displayErrorInfo(objTd, objId, msg);
}

function displayErrorInfo(objTd,objId, msg){

    var objParent = document.getElementById(objTd);
    var objCtrl = document.getElementById(objId);

    // objIdの文字を末尾に追加しているのは、他のコントロールで使用した際IDがかぶるのを防ぐため。
    var objChild = document.getElementById('form_childDiv' + objId);

    // 同じエラーメッセージが何個も表示されないように、既存のエラーメッセージは削除する。
    if(null != objChild)
    {
        objParent.removeChild(objChild);
    }

    if("" != msg) {
        // エラーが有る場合
        objCtrl.style.backgroundColor = "#FADBDA";

        var errorNode = document.createElement("div");
        errorNode.id = "form_childDiv" + objId;
        errorNode.style.color = "#FF0000";
        errorNode.innerText = msg;
        objParent.appendChild(errorNode);
    }else{
        // エラーがない場合
        objCtrl.style.backgroundColor = "#FFFFFF";
    }
}

最初は難しそうだな、と思っていたけど、appendChild()の仕組みを理解すれば、表示の変更自体はそこまで難しくなかった。
ていうか、むしろ正規表現が厄介だった…
RegExp()の引数をクオーテーションで囲む必要がない、ってことになかなか気づかなかった…(Zendの「Zend_Validate_Regex」だと、囲む必要があったはずだけど…)

まあ、この辺は要調査ですね。

C#でCOMを使ってみた。その3

何か、前回から随分間が空いてしまいました。
実家に帰ってたり、仕事のことで悩んでたりで、色々ありまして…すいません。

さて、DirectSoundの件ですが、とりあえず一通りネイティブなDirectXを使用したコードも完成して、コンパイルも通った。
あとは実行&デバッグだと思い、デバッグ実行させたら、こんな実行時エラーが。

failed: System.InvalidCastException : 型 'idirectSoundCaptureBuffer8' の COM オブジェクトをインターフェイス型 'IDirectSoundCaptureBuffer8' にキャストできません。
IID '{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}' が指定されたインターフェイスのCOM コンポーネント上での QueryInterface 呼び出しのときに次のエラーが発生したため、この操作に失敗しました: インターフェイスがサポートされていません
(HRESULT からの例外: 0x80004002 (E_NOINTERFACE))。

キャスト出来ない?
ていうか、インスタンス作成&キャスト自体はこれよりだいぶ前の処理で、問題なく成功しているのに…

とりあえず、

  • 念のためインスタンス作成&キャスト箇所のIID間違いやポインタ確保&解放をチェックしたけど、全く問題なし。
  • レジストリのあるキーの値が壊れているとそういうエラーが発生するらしいけど、それも問題なし。
  • メソッドに[STAThread]属性をつけると直る事があるらしいけど、特に変化なし。(ただ、結果的にはこれに関連する事項だったんですが。)

で、ちょっとハマっていたんですが、下記ブログにそのものズバリの答えが書いてありました。感謝感激です!
architect360.apricot-jp.com

なるほど、要は「COMオブジェクトは(例えクラスメンバ変数などにしたとしても)作成したスレッドとは別のスレッドでそのまま使用することは出来ない」ということですね。
僕のプログラムでは、COMオブジェクトのインスタンスをメインスレッドで作成して、それを別スレッドの音声キャプチャ処理でそのまま使用していたのですが、それが原因だったようです。

なので、音声キャプチャ処理のスレッド内でキャプチャ開始直前にCOMオブジェクトを作成するように変更したら、このエラーは出なくなりました。

まあ、この後も色々あるんですけどね。それはまた後日。


しかし、仕事…というか会社、どうしようなあ。さっさと行動すべきかなあ。
もちろん、ITエンジニア自体を辞めるつもりなんて、さらさらありませんけどね。

C#でCOMを使ってみた。番外編

とりあえず、今日から夏休みです。
取得するのに、相当紆余曲折がありましたが…
(というか、話せば話すほど社長は僕は水と油だということを感じる。色々良くないことも多くなってきたし、試用期間までが潮時、って言うか、それすらも持たないだろうな…)

…てな話はともかく、今回は番外編というか、本当に備忘録のような内容です。


C#C++の型

ネイティブC++の関数を呼び出すとき、ちゃんとC#側で対応する引数の型を指定しないといけないけど、主な型の対応はこんな感じ。(とりあえず、関係しそうなものだけ)

C++C#
WORDshort
DWORDuint
LPSTRstring
LPWSTR
LPCSTR
LPCWSTR
void*IntPtr
HANDLE
LPARAM
WPARAM
HRESULTint
MMRESULT


ネイティブC++関数呼び出し時の引数指定

MSDNなどに記載してあるネイティブC++関数呼び出し時の汎用的なルール。
※あくまで「汎用的」であって、これに当てはまらないケースも当然ある。

C++での引数指定C#での引数指定
純粋な「型名」のみ(例:DWORD、WORD)対応する型の「値渡し」(ref、outキーワードなし)
接頭語「LP」+「型名」(例:LPWORD、LPDWORD)対応する型の「参照渡し」(ref、outキーワードあり)
ポインタ渡し(例:LPWORD*、LPDWORD*)IntPtr型渡し
※コールバック関数を指定する場合は「C#でコールバック関数を使う」を参照のこと。


配列のポインタ

関数に構造体配列のポインタを渡す場合、例えばC++だと

STRUCTURE[] structure = new STRUCTURE[2];
func(&structure);

みたいな書き方でOKだが、C#で同じことをやろうとして、例えば

STRUCTURE[] structure = new STRUCTURE[2];
int str_size = Marshal.SizeOf(structure[0]) + Marshal.SizeOf(structure[1]);
IntPtr ptr_structure = Marshal.AllocCoTaskMem(str_size);
Marshal.StructureToPtr(structure, ptr_structure, false);
func(ptr_structure);

とやっても、コンパイルエラーになってしまう。

で、これをうまくやる方法を調べたのだが、結局は原始的な方法かも知れないが、1要素目のptr_structureの値と各要素のサイズを計算して

STRUCTURE[] structure = new STRUCTURE[2];
int str_size = Marshal.SizeOf(structure[0]) + Marshal.SizeOf(structure[1]);
IntPtr ptr_structure = Marshal.AllocCoTaskMem(str_size);
Marshal.StructureToPtr(structure[0], ptr_structure, false);
Marshal.StructureToPtr(structure[1], (IntPtr)((int)ptr_structure + Marshal.SizeOf(structure[0])), false);

みたいにするしか無いみたい。(もちろん、要素数が多いならループなどを使用するべき。)


構造体の「union」をC#で実装する方法

例えば、DirectSoundなどで使用する、WAVEFORMATEXTENSIBLE構造体は、

typedef struct {
  WAVEFORMATEX  Format;
  union {
    WORD  wValidBitsPerSample;
    WORD  wSamplesPerBlock;
    WORD  wReserved;
  } Samples;
  DWORD   dwChannelMask; 
  GUID    SubFormat;
} WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE;

となっている。

この構造体の「union」に該当するキーワードはC#にはないが、「StructLayout」と「FieldOffset」の指定をうまく使うことで、構造体のunionと同じことを行うことが出来る。

// FieldOffsetを自分で指定するので、StructLayoutはLayoutKind.Explicitにしないといけない。
[StructLayout(LayoutKind.Explicit)]
private struct WAVEFORMAT_EXTENSIBLE
{
    // wValidBitsPerSample,wSamplesPerBlock,wReservedのFieldOffsetを同じにして「union」と同じことを実現している。
    [FieldOffset(0)]
    public WAVEFORMATEX Format;
    [FieldOffset(20)]
    public ushort wValidBitsPerSample;
    [FieldOffset(20)]
    public ushort wSamplesPerBlock;
    [FieldOffset(20)]
    public ushort wReserved;
    [FieldOffset(22)]
    public uint dwChannelMask;
    [FieldOffset(26)]
    public Guid SubFormat;
}


…すいません。ちょっと手抜き感が否めないですが、今回はこれでご勘弁を。

C#でCOMを使ってみた。その2

どうしても今月中に役所へ行かなければならないので、申し訳ないと思いながらも12日に休暇申請したら「正直、よくそんな面の厚いことが出来るな、という感じだけどね」みたいな事を言われた。
バイ、これは早急に身の振り方を考えないと。


…というわけで、その1の続きです。


COMインターフェースのインスタンス作成・キャスト

「コクラスが持つインターフェースにアクセスする」場合や「定義したCOMインターフェースと互換性がある」場合は、メソッドなどを実行しなくても、キャストを実行するだけでCOMインターフェースのインスタンスを作成できます。

DirectSoundCapture8Class DSC = new DirectSoundCapture8Class();
IDirectSoundCapture8 iDSC = (IDirectSoundCapture8)DSC;

ただキャストするだけではエラーになる場合は(ネイティブ側のCOMインターフェースポインタを受け取る場合など)、MarshalクラスのGetTypedObjectForIUnknown()メソッドの戻り値をキャストすればOKです。(これを発見するのにすごく時間がかかった…)

public static object GetTypedObjectForIUnknown(
  IntPtr pUnk,    // ネイティブ側のCOMインターフェースポインタ
  Type t          // (COMインターフェースなどの)型
)


// ptr_iDSCB8にネイティブ側のCOMインターフェースポインタが格納されているものとする。
IDirectSoundCaptureBuffer8 iDSCB8 = (IDirectSoundCaptureBuffer8)Marshal.GetTypedObjectForIUnknown(ptr_iDSCB8, typeof(IDirectSoundCaptureBuffer8));


ネイティブ側のCOMインターフェースポインタの取得

ネイティブ側のCOMインターフェースポインタ取得ですが、

1.MarshalクラスのQueryInterface()メソッドを使う方法
C++での方法ですね。

public static int QueryInterface(
    IntPtr pUnk,    // 取得したいCOMインターフェースの取得をサポートしているCOMインターフェースのポインタ
    ref Guid iid,   // 取得したいCOMインターフェースのIID
    out IntPtr ppv  // 取得したいCOMインターフェースのポインタが格納される
)


// ptr_iDSCB8にIDirectSoundCaptureBuffer8インターフェースポインタが入っていて、
// 取得したIDirectSoundNotify8インターフェースポインタをptr_iDSN8に格納したい場合。
// guidにはIDirectSoundNotify8インターフェースポインタのIIDが格納されているものとする。
int getNotifyResult = Marshal.QueryInterface(ptr_iDSCB8, ref guid, out ptr_iDSN8);
IDirectSoundNotify8 iDSN8 = (IDirectSoundNotify8)Marshal.GetTypedObjectForIUnknown(ptr_iDSN8, typeof(IDirectSoundNotify8));


2.普通にインターフェースポインタを取得できるネイティブ側のメソッドを使用する。

// (例)DirectSoundのDirectSoundCaptureCreate8()メソッドを呼び出した場合。
// guidにIDirectSoundCapture8インターフェースのIIDを渡すと、正しく処理が行われた場合、ptr_iDSC8に
// IDirectSoundCapture8インターフェースポインタが格納される。(第三引数はnull固定。)
int createCaptureResult = DirectSoundCaptureCreate8(ref guid, out ptr_iDSC8, null);
IDirectSoundCapture8 iDSC8 = (IDirectSoundCapture8)Marshal.GetTypedObjectForIUnknown(ptr_iDSC8, typeof(IDirectSoundCapture8));

う~ん、ざっと説明してきましたが、分かりにくい内容になってしまったような…申し訳ないです。


【追記】
冒頭の件、別に「5連休にしたい!」とかそういう意図ではなく「(どうせ有休で休む人が多いんだし、他の人にあわせて)休むときは休む、働くときは働く」っていう考えだったからこの日にしたんだけど…
それを「面の皮が厚い」とか「他の日にしない理由が見つからない」とか言われるのであれば、真剣に考えないとねえ。