2005年05月08日
川俣晶の縁側ソフトウェア技術雑記total 19058 count

C++/CLIでネイティブな文字列とmanagedな文字列を相互変換する「試行」その2

Written By: 川俣 晶連絡先

 C++/CLIでネイティブな文字列とmanagedな文字列を相互変換する「試行」その1ではマーシャリング関係の機能を使わないでサンプルソースを書いてみました。

 今回は、マーシャリング関係の機能を活用してこれをよりコンパクトに書き直してみます。

サンプルソース §

 Visual C++ Express 2005 Beta2で、managedコンソールアプリケーションのテンプレートでプロジェクト作成後に、以下のソースを入力します。

#include "stdafx.h"

// あえてprintfを使うのincludeしておく

#include <stdio.h>

using namespace System;

// ここからはネイティブコードにしてちょ

#pragma unmanaged

// printfでcharのポインタで受けた文字列を出力するネイティブコード関数

void unmanagedOutput(const char * str)

{

    printf("native string: %s\n",str);

}

// いかにも古き良きCらしいコーディングで文字列を生成するネイティブコード関数

// むろん、以下の関数はバッファオーバーランの可能性がある悪い関数である

void unmanagedCreateString(char * str)

{

    // 要するにアルファベット大文字A~Zの生成

    for( int i=0; i<26; i++ )

    {

        *str++ = 'A' + i;

    }

    *str = '\0';

}

// ここからはmanagedコードに戻してちょ

#pragma managed

// managedコードで文字列を加工する関数。小文字にしてみる

String ^ managedModefyString( String ^ str )

{

    return str->ToLower();

}

int main(array<System::String ^> ^args)

{

    // 入れ物になる配列。マジックナンバー27はお行儀が悪いぞ!

    char test[27];

    // ネイティブコード関数で配列に文字列をセットさせる

    unmanagedCreateString(test);

    // managedコードで文字列を加工する

    // char配列からSystem::Stringに直すのは、

    // PtrToStringAnsiメソッドに任せることができる

    String ^ result = managedModefyString( 

        System::Runtime::InteropServices::Marshal::PtrToStringAnsi((IntPtr)test) );

    // System::StringからANSI文字に直すのは

    // StringToHGlobalAnsiメソッドに任せることができる

    IntPtr ptr = System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi( result );

    try

    {

        // ネイティブコード関数から結果を出力

        // IntPtr型の値からToPointerメソッドを呼んでvoidのポインターにした上でキャスト

        // (もっとスマートな書き方はあり得るか?)

        unmanagedOutput( (const char*)ptr.ToPointer() );

    }

    finally

    {

        // おっと、後始末を忘れちゃいけません!

        System::Runtime::InteropServices::Marshal::FreeHGlobal(ptr);

    }

    // おしまい

    return 0;

}

実行結果 §

native string: abcdefghijklmnopqrstuvwxyz

解説 §

 ANSI文字列ポインターからSystem::String型に変換するには以下のメソッド。

System::Runtime::InteropServices::Marshal::PtrToStringAnsi

 System::String型からANSI文字列ポインターに変換するには以下のメソッド。

System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi

 同様にUnicode文字列とのポインターとの相互変換はAnsiのかわりにUniという名前を持ったメソッド。ANSI/Unicodeの自動判定はAnsiのかわりにAuto。

 StringToHGlobalAnsi等は、文字列をWindowsのグローバルヒープ(GlobalAllocする領域)に(たぶん)確保します。従って、この領域は必ず開放しなければなりません。解放するには、以下のメソッドを使います。

System::Runtime::InteropServices::Marshal::FreeHGlobal(ptr);

 これらのメソッドは、ポインターではなくIntPtr型の値を扱うので、それとポインター型の間を適切に相互変換する必要があります。必要に応じてキャストやToPointerメソッドなどを使います。

感想 §

 結局、C++/CLIの問題ではなく、System::Runtime::InteropServices::Marshalクラスの問題になってしまいました。あれまあ。

 つまりは、昔からそこにあった機能の問題ということで、単に使う機会が無く知らなかっただけ、ということですね。

Facebook

キーワード【 川俣晶の縁側ソフトウェア技術雑記
【技術雑記】の次のコンテンツ
2005年
05月
08日
.NET FrameworkのDrawImageメソッドでピクセル等倍での描画を強制する方法
3days 0 count
total 8201 count
【技術雑記】の前のコンテンツ
2005年
05月
07日
C++/CLIでmanagedなバイト配列をネイティブなバイト配列を処理する関数に渡す
3days 0 count
total 53069 count

このサイト内の関連コンテンツ リスト

2005年
05月
07日
C++/CLIでネイティブな文字列とmanagedな文字列を相互変換する「試行」その1
3days 0 count
total 9965 count

このコンテンツを書いた川俣 晶へメッセージを送る

[メッセージ送信フォームを利用する]

メッセージ送信フォームを利用することで、川俣 晶に対してメッセージを送ることができます。

この機能は、100%確実に川俣 晶へメッセージを伝達するものではなく、また、確実に川俣 晶よりの返事を得られるものではないことにご注意ください。

このコンテンツへトラックバックするためのURL

http://mag.autumn.org/tb.aspx/20050508012415
サイトの表紙【技術雑記】の表紙【技術雑記】のコンテンツ全リスト 【技術雑記】の入手全リスト 【技術雑記】のRSS1.0形式の情報このサイトの全キーワードリスト 印刷用ページ

管理者: 川俣 晶連絡先

Powered by MagSite2 Version 0.36 (Alpha-Test) Copyright (c) 2004-2021 Pie Dey.Co.,Ltd.