RSS

カテゴリー別アーカイブ: 未分類

Visual Studio 2017 で MFC アプリ開発機能を追加するには

Visual Studio 2015 では Visual C++ プロジェクトのテンプレートに MFC アプリ開発が含まれていましたが、Visual Studio 2017 では、なぜか含まれなくなっています。

しかし、後からこのテンプレートを追加することができます。

「新しいプロジェクト」ダイアログを開いて、テンプレートリストの一番下の「Visual Studio インストーラを開く」をクリックします。

New Projects.png

下のようなインストーラが開くので、「概要」の「C++によるデスクトップ開発」のオプションで必要なもの(ここでは「MFCとATLのサポート」)をチェックします。

SDK Installer.jpg

最後に「変更」ボタンをクリックしますが、その前に Visual Studio 2017 は閉じておきます。

インストールが終了したら、Visual Studio 2017 を再起動して、プロジェクトのテンプレートに追加した項目が含まれていることを確認します。

MFC Template

 

広告
 
コメントする

投稿者: : 2018/01/11 投稿先 MSC, 未分類

 

VC++ で古いソースをコンパイルするとエラーになる件

Visual Studio 2017 で VC++ の空プロジェクトを作成し、そこに古いソースを追加してビルドしてみると、実行がうまくいきません。

古いソースは SJIS で書かれているのですが、 Visual Studio 2017 の VC++ プロジェクトはデフォルトは Unicode です。

プロジェクトのプロパティダイアログを開き、構成プロパティ-全般の中で「文字セット」を「マルチバイト文字を使用する」に変更してビルドしなおすと正常に動作しました。

その他、管理者として Visual Studio を起動しないとエラーになることもあるようです。

 

 

 
コメントする

投稿者: : 2018/01/07 投稿先 未分類

 

VC++ のビルドで必要な Windows.h が見つからない件

Visual Studio 2017 で Visual C++ のプロジェクトを作成してビルドしてみたところ、「Windows.h が見つからない」というエラーが出ました。

どうも、プロジェクトのプロパティページを開いてインクルードパスを見てみると $(IncludePath) という設定になっています。

同様にライブラリパスは $(LibraryPath) になっていました。

どうも、IncludePath の内容が間違っているようです。これを修正すれば直るはずですが、他のプロジェクトに影響が出るかもしれないので、ここはインクルードパスを追加してみました。

C:\Program Files (x86)\Microsoft SDKs\Windows の下にバージョンの異なる SDK フォルダがずらりとあったので、その中から適当なものを選んで Include フォルダのパスを追加しました。

同様に、LibraryPath でもエラーが出るので、同じ SDK のLib フォルダのパスを追加しました。

これで、エラーは消えてコンパイルできました。


 

参考

このIncludePath, LibraryPath はプロジェクトのプロパティでVC++ディレクトリの中のインクルードディレクトリを編集すると表示されるダイアログで確認できます。

IncludePath.png

 

 
コメントする

投稿者: : 2018/01/07 投稿先 未分類

 

関数のパラメータの参照渡しとはどういうことなのか?

関数呼び出しで、関数(メソッド)のパラメータの渡し方には「値渡し」と「参照渡し」というのがあります。

ただ、Java や JavaScript には言語仕様としての参照渡しはなく、常に値渡しになります。

参照渡しの例ですが、最初に C# を例にして説明します。次のサンプルは2つのパラメータの値を交換するのに参照渡しを使っています。

using System;

public class SwapFunc
{
  static void Main(String[] args)
  {
    int x = 0;
    int y = 1;

    // x と y の値を交換
    Swap(ref x, ref y);

    Console.WriteLine("x = {0:d}, y = {1:d}\n", x, y);
  }

  // x と y の値を交換するメソッド
  static void Swap(ref int x, ref int y)
  {
    var u = x;
    x = y;
    y = u;
  }
}

これの IL (中間コード) は次のようになります。

コメントに動作を書きましたが、正確かどうかは別として、スタックマシン (仮想マシン) を使って、スタックフレーム上のデータをプッシュしたりポップしたりして計算を行っています。

このまま実行すると遅いので、通常、さらにネイティブコードに変換されて実行されます。

参照渡しに関わる部分は Main では、IL_0005 と IL_0006 のあたりです。ここで、スタックフレーム上のデータ x, y のアドレスをスタックに積んでいます。

関数 Swap 側で参照渡しに関わる部分は、ldind 命令を使っているあたりです。この命令は指定したオペランドの内容をアドレスとみなして、そのアドレスの行った先のデータをスタックに積んでいます。

//  Microsoft (R) .NET Framework IL Disassembler.  Version 4.0.30319.18020
//  Copyright (c) Microsoft Corporation. All rights reserved.



// Metadata version: v4.0.30319
.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
  .ver 4:0:0:0
}
.assembly Swap
{
  .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) 
  .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
                                                                                                             63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 )       // ceptionThrows.
  .hash algorithm 0x00008004
  .ver 0:0:0:0
}
.module Swap.exe
// MVID: {DDFC4E86-9AF5-4AC3-927E-267DAB2AEE1E}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003       // WINDOWS_CUI
.corflags 0x00000001    //  ILONLY
// Image base: 0x04700000


// =============== CLASS MEMBERS DECLARATION ===================

.class public auto ansi beforefieldinit SwapFunc
       extends [mscorlib]System.Object
{
  .method private hidebysig static void  Main(string[] args) cil managed
  {
    .entrypoint
    // コード サイズ       39 (0x27)
    .maxstack  3
    .locals init (int32 V_0,
             int32 V_1)
    IL_0000:  nop
    IL_0001:  ldc.i4.0  0 をプッシュ。
    IL_0002:  stloc.0  0 をポップしスタックフレーム V_0 に保存
    IL_0003:  ldc.i4.1  1 をプッシュ。
    IL_0004:  stloc.1  1 をポップしてスタックフレーム V_1 に保存
    IL_0005:  ldloca.s   V_0  V_0 のアドレスをプッシュ。
    IL_0007:  ldloca.s   V_1  V_1 のアドレスをプッシュ。
    IL_0009:  call       void SwapFunc::Swap(int32&,  Swap をコール
                                             int32&)
    IL_000e:  nop   何もしない。
    IL_000f:  ldstr      "x = {0:d}, y = {1:d}\n"  フォーマットのアドレスをプッシュ
    IL_0014:  ldloc.0  V_0 の値をプッシュ。
    IL_0015:  box        [mscorlib]System.Int32 スタックのトップをボクシング
    IL_001a:  ldloc.1  V_1 の値をプッシュ。
    IL_001b:  box        [mscorlib]System.Int32 スタックのトップをボクシング
    IL_0020:  call       void [mscorlib]System.Console::WriteLine(string, Console.WriteLine をコール
                                                                  object,
                                                                  object)
    IL_0025:  nop  何もしない。
    IL_0026:  ret  もどる。
  } // end of method SwapFunc::Main

  .method private hidebysig static void  Swap(int32& x,
                                              int32& y) cil managed
  {
    // コード サイズ       12 (0xc)
    .maxstack  2
    .locals init (int32 V_0)
    IL_0000:  nop
    IL_0001:  ldarg.0  引数0をプッシュ。
    IL_0002:  ldind.i4 スタックトップをアドレスとしてその行った先の内容をプッシュ。
    IL_0003:  stloc.0  ローカル変数 0 に格納。
    IL_0004:  ldarg.0  引数0をプッシュ。
    IL_0005:  ldarg.1  引数1をプッシュ。
    IL_0006:  ldind.i4  スタックトップをアドレスとして、その行った先の内容をプッシュ。
    IL_0007:  stind.i4  スタックトップをアドレスとして、その行った先へストア。
    IL_0008:  ldarg.1 引数1をプッシュ。
    IL_0009:  ldloc.0 ローカル変数0をプッシュ。
    IL_000a:  stind.i4 その行った先の内容をプッシュ。
    IL_000b:  ret
  } // end of method SwapFunc::Swap

  .method public hidebysig specialname rtspecialname 
          instance void  .ctor() cil managed
  {
    // コード サイズ       7 (0x7)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
    IL_0006:  ret
  } // end of method SwapFunc::.ctor

} // end of class SwapFunc


// =============================================================

// *********** 逆アセンブルが完了しました ***********************
// 警告: Win32 リソース ファイル C:\workspace\dotNET\IL\Swap\Swap.res を作成しました。

次に、C 言語の例を見てみます。

C 言語の場合、VM (仮想マシン) は使用しない、つまり、いきなりネイティブコードを生成します。

ここでは、PC で使われている x86 と x64 について述べます。RISC や IBM などでは、基本的考え方は同じはずですが、Calling Convention (呼び出し規約) がそれぞれ異なるのでいろいろ異なります。

まず、C のソースですが、下のようなものとします。

#include <stdio.h>

void swap(int*, int*);

int main(int argc, char* argv[]) {
  int x = 0;
  int y = 1;

  swap(&x, &y);

  printf("x = %d, y = %d\n", x, y);

  return 0;
}

void swap(int* x, int* y) {
  int u = *x;
  *x = *y;
  *y = u;
}

 

これのコンパイル結果は、次のようになります。(x86 の場合)

	.file	"Swap.c"
	.section	.rodata
.LC0:
	.string	"x = %d, y = %d\n"
	.text
.globl main
	.type	main, @function
main:
	leal	4(%esp), %ecx
	andl	$-16, %esp
	pushl	-4(%ecx)
	pushl	%ebp
	movl	%esp, %ebp
	pushl	%ecx
	subl	$36, %esp
	movl	$0, -8(%ebp)  0 をスタックフレームのローカルアドレスに保存(x)
	movl	$1, -12(%ebp)  1 をスタックフ
レームのローカルアドレスに保存(y)
	leal	-12(%ebp), %eax y のアドレスを EAX にロード
	movl	%eax, 4(%esp) EAX をスタックに積む。
	leal	-8(%ebp), %eax x のアドレスを EAX にロード
	movl	%eax, (%esp) EAX をスタックに積む。
	call	swap  関数 swap を呼び出す。
	movl	-12(%ebp), %eax
	movl	-8(%ebp), %edx
	movl	%eax, 8(%esp)
	movl	%edx, 4(%esp)
	movl	$.LC0, (%esp)
	call	printf
	movl	$0, %eax
	addl	$36, %esp
	popl	%ecx
	popl	%ebp
	leal	-4(%ecx), %esp
	ret
	.size	main, .-main
.globl swap
	.type	swap, @function
swap:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$16, %esp
	movl	8(%ebp), %eax 後から積んだパラメータ(x)を EAX にロード
	movl	(%eax), %eax  EAX の行った先のデータを EAX にロード
	movl	%eax, -4(%ebp) EAX をローカル変数に保存。
	movl	12(%ebp), %eax 最初に積んだパラメータ(y)を EAX にロード
	movl	(%eax), %edx  EAX の行った先のデータを EDX にロード
	movl	8(%ebp), %eax 後から積んだパラメータ(x)を EAX にロード
	movl	%edx, (%eax) EDX を EAX の行った先に保存
	movl	12(%ebp), %edx 最初に積んだパラメータ(y)を EDX にロード
	movl	-4(%ebp), %eax ローカル変数の内容を EAX にロード
	movl	%eax, (%edx) EAX を EDX の行った先に保存。
	leave
	ret
	.size	swap, .-swap
	.ident	"GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-54)"
	.section	.note.GNU-stack,"",@progbits

x64 の場合は、関数の呼び出し規約が異なっており、整数や浮動小数点数は最適化しなくてもレジスタ渡しになります。

これは、x64 では、汎用レジスタが8本から16本に増えたためで、余ったレジスタを関数のパラメータとして活用しています。

	.file	"Swap.c"
	.section	.rodata
.LC0:
	.string	"x = %d, y = %d\n"
	.text
	.globl	main
	.type	main, @function
main:
.LFB0:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	subq	$32, %rsp
	movl	%edi, -20(%rbp)
	movq	%rsi, -32(%rbp)
	movl	$0, -8(%rbp)
	movl	$1, -4(%rbp)
	leaq	-4(%rbp), %rdx  RDX には y のアドレスが入る。
	leaq	-8(%rbp), %rax  RAX には x のアドレスが入る。
	movq	%rdx, %rsi  呼び出し規約に基づいて、パラメータを RSI レジスタ渡しにしている。
	movq	%rax, %rdi  呼び出し規約に基づいて、パラメータを RDI レジスタ渡しにしている。
	call	swap
	movl	-4(%rbp), %edx
	movl	-8(%rbp), %eax
	movl	%eax, %esi
	movl	$.LC0, %edi
	movl	$0, %eax
	call	printf
	movl	$0, %eax
	leave
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE0:
	.size	main, .-main
	.globl	swap
	.type	swap, @function
swap:
.LFB1:
	.cfi_startproc
	pushq	%rbp
	.cfi_def_cfa_offset 16
	.cfi_offset 6, -16
	movq	%rsp, %rbp
	.cfi_def_cfa_register 6
	movq	%rdi, -24(%rbp)
	movq	%rsi, -32(%rbp)
	movq	-24(%rbp), %rax
	movl	(%rax), %eax
	movl	%eax, -4(%rbp)
	movq	-32(%rbp), %rax
	movl	(%rax), %edx
	movq	-24(%rbp), %rax
	movl	%edx, (%rax)
	movq	-32(%rbp), %rax
	movl	-4(%rbp), %edx
	movl	%edx, (%rax)
	popq	%rbp
	.cfi_def_cfa 7, 8
	ret
	.cfi_endproc
.LFE1:
	.size	swap, .-swap
	.ident	"GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4"
	.section	.note.GNU-stack,"",@progbits

 

参照渡しができない言語の場合、言語仕様として参照表現がないというだけで、参照渡しは使われています。

パラメータが値渡しされる場合は、汎用レジスタに値がロードできるもの、具体的には整数や浮動小数点数が値渡しになり、汎用レジスタに値がロードできないもの、具体的には配列や一般のオブジェクトが参照渡しになります。

したがって、参照渡しされる型を利用すれば、swap 関数と同様の機能が実現できます。

つぎのコードは JavaScript で参照渡しと同様の機能を実現する例です。配列は参照渡しなので、swap 関数により2つのパラメータの中身が交換されます。

 

'use strict';

const swap = (x, y) => {
    let u = x[0];
    x[0] = y[0];
    y[0] = u;
};

var a = [0];
var b = [1];

swap(a, b);

console.log("%i, %i", a, b);


 

 
コメントする

投稿者: : 2017/11/30 投稿先 未分類

 

ASP.NET: アプリケーションのバージョンを表示するには

アプリケーションのプロパティの「アセンブリ情報」で定義したバージョンをWebページに表示したい場合、MVC の場合なら、Views/Shared/_Layout.vbhtml (または .cshtml) に次のように1行追加するとよい。(場所は任意)

Version @ViewContext.Controller.GetType().Assembly.GetName().Version

画面上では、次のような感じで表示される。

 
コメントする

投稿者: : 2017/06/04 投稿先 未分類

 

FREETEL KATANA01 (Windows Mobile) に機種変更したとき

freetel はいわゆる格安スマホで有名ですが、これまで使っていた priori2 (Android 5) から KATANA01 (Windows Mobile) に機種変更しました。

ここで問題が・・・ネットにつながらない!!

新規購入のときは、SIMの設定がされているようですが、機種変更だとSIMの再設定が必要のようです。

これがわかりづらいです。下記のURLを開いて設定を行いますが、素人には苦しいですね。

https://www.freetel.jp/sim/apn_Setting/

特に最後のプロファイルの設定が手動でやらなければならず(登録済み設定が機能しなかったため)、しかも画像の入力項目が空欄になっていて横に設定方法が文言で書かれているのはいただけません。

さらに、MMS??のURLがないとエラーになるのですが、その設定方法がどこにも書かれてありません。適当に、http::/freetel.jp とか入れたら通りましたが、これでいいんでしょうかね。

katana01setting1

KATANA01Setting2.png

 
コメントする

投稿者: : 2017/03/03 投稿先 未分類

 

ASP.NET:HTMLタグを含む文字列がSQL Serverのテーブルに書き込みできない件

ASP.NET ではデフォルトでデータベースへ格納する文字列の検証をしているようで、HTMLのscriptタグを含んだ文字列をテーブルへ書こうとするとエラーになってしまいました。

aspnet_sqlserver_script

これを回避するには、ValidateInput 属性を false にしてやるとよいようです。

        [ValidateInput(false)]
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult ViewAddClip(Pixels p)
        {
       ....
        }
 
コメントする

投稿者: : 2017/01/29 投稿先 未分類