標準出力

新しいもの、変わらないこと 自分の頭を通して考えてみました (stdout)

Swift - Interoperability with c lang

The function is shown below obtains the machine model by calling the sysctlbyname function. 

 

    

    func getModelNameBySysCtl() -> String{

        let name = "hw.machine"

        var size: Int = 0

        var result: String = ""

        var funcRet: Int32 = -1

        

        sysctlbyname(

            name,

            nil,

            &size,

            nil,

            0

        )

        

        if size > 0 {

            let valuePointer = UnsafeMutablePointer<CChar>.allocate(capacity: size)

            valuePointer.initialize(to: 0)

            

            funcRet = sysctlbyname(

                name,

                valuePointer,

                &size,

                nil,

                0

            )

            

            if funcRet == 0{

                result = String(cString: valuePointer)

            }

            valuePointer.deinitialize(count: size)

            valuePointer.deallocate()

        }

        

        return result

    }

 

Points of the above code

  • String to UnsafePointer<CChar>
  • Manage UnsafeMutablePointer<CChar>

WOL(Wake on LAN)設定でハマった点

 下記構成でWake on LAN(以下、WOL)を有効にしようとOS側の設定("高速スタートアップを有効にする"には、チェックを入れている)を行い、別マシンよりマジックパケットをPCに送出するも起動しない。

MB: ASUS M5A99X EVO
NIC: Realtek 8111E PCI-E Gigabit LAN コントローラ
OS: Windows10 Pro 64bit (Build number: 14393.693)

 試しに、スリープ状態にしてマジックパケットを送出すると起動する。色々調べた結果、UEFIの"ErP Ready"機能が有効(Enabled)になっているのが原因だった。本機能が有効になっているとACPIのS5 state にてWOLは無効になるとMBの取説に書いてあった。

 以降の手順で"ErP Ready"を無効化して、WOLを有効にした。
[Advanced->APM]

f:id:kuni255:20170222002102j:plain

ErpReady が Enabled になっているので Disabled に変更。

f:id:kuni255:20170222002040j:plain

"Power On By PME Device" を Enabled に変更した。

f:id:kuni255:20170222002231j:plain

後は、変更を保存して設定画面を抜けます。



 

クロスプラットフォームなC/C++ IDE CLion を使ってみた

標題通り Windows,Linux,Mac で使えるC/C++IDE CLionMac OS X (10.9)で使ってみた。

現在のところβ版扱いで60日間に限り無料で使える。



特徴としては、以下2点が挙げられる。
コンパイル関係の設定をCMakeList.txtに書いていく
Vim Emulator

試しにOpenCVを使ってMBAiSightのキャプチャをしてみた。OpenCVはVer.2.4.9をソースからコンパイルして/opt/OpenCV/2.4.9配下にインストールしたものを利用する。
以下main.cpp
#include <iostream>#include "opencv2/objdetect/objdetect.hpp"#include "opencv2/highgui/highgui.hpp"#include "opencv2/imgproc/imgproc.hpp"
using namespace std;using namespace cv;

int main() {
CvCapture *capture; Mat frame, frameCopy, image;
capture = cvCaptureFromCAMCV_CAP_ANY;()
if(capture== NULL){
cout << "Failed to open camera" <<endl;
return -1; }

cvNamedWindow("Result", CV_WINDOW_AUTOSIZE); cout << "Captureing... " << endl;
while (1) {
IplImage *iplImage = cvQueryFrame(capture); frame = iplImage; if (frame.empty()) break; if (iplImage->origin == IPL_ORIGIN_TL) {
frame.copyTo(frameCopy); } else {
flip(frame, frameCopy, 0); }
cvShowImage("result", iplImage); if (waitKey(10) >= 0) break; }

cvReleaseCapture(&capture;); cvDestroyWindow("Result"); return 0;}
そして、以下がCMakeList.txt
cmake_minimum_required(VERSION 2.8.4)
project(helloCLion)

set(SOURCE_FILES main.cpp)
add_executable(helloCLion ${SOURCE_FILES})

set(OPENCV_PREFIX_PATH /opt/OpenCV/2.4.9)
set(OpenCV_LIBS opencv_core opencv_imgproc opencv_highgui)
FIND_PACKAGE(OpenCV REQUIRED)
INCLUDE_DIRECTORIES(${OPENCV_PREFIX_PATH}/include)
LINK_DIRECTORIES(${OPENCV_PREFIX_PATH}/lib)
TARGET_LINK_LIBRARIES(helloCLion ${OpenCV_LIBS})
7行目以降がOpenCV関係の設定

問題は、デバッグしようとするとコンソールに下記が出力されデバッグできない。
/Users/hayato/Library/Caches/clion10/cmake/generated/6982c880/6982c880/Debug/helloCLion
During startup program exited with code 1.

Process finished with exit code 0

CLionはデバッガとして同梱の(/Applications/CLion EAP.app/Contents/bin/gdb/bin/gdb)を使っているらしく、このgdbにコード証明書があたっていないのが原因かと考えコード証明書をあててみたが現象は改善せず。

Windows の共有ライブラリロード時のサーチパスの優先順位

Linux の場合LD_LIBRARY_PATHに依るけどWindowsの場合は、
[1] アプリケーションがロードされたディレクトリ
[2] System directory
[3] 16bit system directory
[4] Windows directory
[5] カレントディレクトリ
[6] 環境変数PATH

の順らしいです。ということで検証してみた。今回は、検証用の自分自身が配置されている場所を返すプロシージャを含む"studyTest.dll"とそれを用いるコードを書いて確認してみた。

dllを使用する側のプロセス生成時のカレントディレクトリを起点としたディレクトリとファイルツリーは、下記のようになっている。

.\
├─bin
│      studyTest.dll
│      useDll.exe
│    
├─lib
│      studyTest.dll
│    
└─sub
        studyTest.dll

[コマンドプロンプトにおける実行履歴]
set PATH=%CD%\lib;%PATH%
> .\bin\useDLL.exe



"call_Proc"ボタンを押下。

>move .\bin\studyTest.dll .\bin\studyTest_A.dll
"call_Proc"ボタンを押下。

>move C:\Windows\SysWOW64\studyTest.dll C:\Windows\SysWOW64\studyTest_A.dll
"call_Proc"ボタンを押下。

>move C:\Windows\studyTest.dll C:\Windows\studyTest_A.dll
"call_Proc"ボタンを押下。

>move .\sub\studyTest.dll .\sub\studyTest_A.dll
"call_Proc"ボタンを押下。






DLLを使うコード
unit dllStudy;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
  shlObj;

type
  TuseDLL = class(TForm)
    callProc: TButton;
    Edit1: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Edit2: TEdit;
    Edit3: TEdit;
    Label3: TLabel;
    procedure callProcClick(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    { Private 宣言 }
    procedure updateCurDir();
  public
    { Public 宣言 }
  end;

  Type TWhereAreYou = procedure(); stdcall;

var
  useDLL: TuseDLL;
  whereAreYou : TWhereAreYou;

implementation

{$R *.dfm}


procedure TuseDLL.callProcClick(Sender: TObject);
var
  Handle : THandle;
begin
  Handle := LoadLibrary('studyTest.dll');
  if(Handle0) then begin
    @whereAreYou := GetProcAddress(Handle, 'whereAreYou');
    if(@whereAreYounil) then  whereAreYou;
    FreeLibrary(Handle);
  end;
end;

procedure TuseDLL.FormShow(Sender: TObject);
var
 cSysDir : array[0..MAX_PATH] of char;
 cWinsDir : array[0..MAX_PATH] of char;
begin
  // change current directory
  ChDir('.\Sub');
  updateCurDir;

  GetSystemDirectory(cSysDir, GetSystemDirectory(cSysDir,1)+1);
  SHGetSpecialFolderPath(Handle, cSysDir, CSIDL_SYSTEMX86, False);
  Edit2.Text := String(cSysDir);
  GetWindowsDirectory(cWinsDir, GetWindowsDirectory(cWinsDir, 1)+1);
  Edit3.Text := String(cWinsDir);
end;

procedure TuseDLL.updateCurDir;
begin
  Edit1.Text := GetCurrentDir;
end;

end.


References
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682586(v=vs.85).aspx#standard_search_order_for_desktop_applications

PLEX Multimedia Server の構築 on FreeBSD 9.1 STABLE

PLEX Multimedia Server を構築する。なお、FreeBSDは、サポートはされていないので自己責任で。。。

[1] ローカルからのアクセスまで

ports にてサーバーソフトウェアをインストールする。

cd /usr/ports/multimedia/plexmediaserver
make config-recursive
make
make install

起動時にデーモンが起動するように/etc/rc.confに下記を追記

plexmediaserver_enable="YES"

サーバーの起動
/usr/local/etc/rc.d/plexmediaserver start

ブラウザにて 下記アドレスにアクセス

http://[server-address]:32400/manage

下記のようなページが表示されればここまではOK


[2] 外からのアクセス
(1) ルーターの設定
PLEX Multimedia Serverは、TCPの32400番ポートを使うのでルーターの外からサーバーの32400番ポート宛のパケットを通すようにルーターのファイヤーウォールの設定を変更しておく。
 また、NATを使っている場合は、ルーターの外側のIPアドレスの32400番ポートへの接続要求をサーバーの32400番ポートへ転送するように静的NATのエントリを追加しておく。 参考

(2) PLEXの設定
次に、https://plex.tv/ にアクセスしてplexのアカウントを作成。

"[1] ローカルからのアクセスまで"にてアクセスしたローカルに建てたサーバーのページの右上のサインインをクリックして作成したアカウントでログインする。サインインできたら右上の歯車の設定アイコンをクリックして、同アイコンより下に表示される"Server"をクリック。
Friendry name がホスト名になっている場合は、FQDNに変更しておく。


さらに、右側の"Connect"をクリックして、"Manually specify port"にチェック、テキストボックス"32400"が入力されていることを確認して、"Retry"ボタンを押下。下記画像のように2つのチェックが付けばOK。



実際に外からアクセスできるかどうか試してみる。