- PR -

[C#] DLL 関数の呼び出しについて

1
投稿者投稿内容
Pluto
常連さん
会議室デビュー日: 2002/07/01
投稿数: 40
投稿日時: 2004-12-20 18:41
いつも御世話になります。

下記のような DLL 関数を C# で呼び出そうとしてるのですが、
拙者が未熟者であるため、その方法が分かりません。

// DLL 関数
// lpResponse: 取得した値を格納するバッファのポインタ
// dwLen: 値を格納するバッファのサイズ (バイト単位)
// lpdwReadLen: 取得した値のバイト数を格納するポインタ
DWORD WINAPI GetValue(LPBYTE lpResponse, DWORD dwLen, LPDWORD lpdwReadLen);


C++ の場合、以下のように書いて実行できるのですが、
C# ではどのように記述していいものか・・・
(特に LPBYTE、_TCHAR をどうしていいのか・・・)

// C++ の場合、
_TCHAR res[BUFSIZ] = {NULL};
DWORD len;

GetValue((LPBYTE)&res[strlen(res)], sizeof(res) - strlen(res), &len)


どなたかご教示の程、宜しくお願い申し上げます。

mei
大ベテラン
会議室デビュー日: 2003/04/08
投稿数: 114
投稿日時: 2004-12-20 22:40
こんばんは、meiです。

引用:

Plutoさんの書き込み (2004-12-20 18:41) より:

// DLL 関数
// lpResponse: 取得した値を格納するバッファのポインタ
// dwLen: 値を格納するバッファのサイズ (バイト単位)
// lpdwReadLen: 取得した値のバイト数を格納するポインタ
DWORD WINAPI GetValue(LPBYTE lpResponse, DWORD dwLen, LPDWORD lpdwReadLen);



LPBYTEはunsigned char*なのでbyteの配列を渡してあげればいいのではないでしょうか? また、DWORDはunsigned longなのでuint、LPDWORDはuintのアドレスが渡せればいいので、ref uintでいいでしょう。C#の型については.NET Frameworkのドキュメントに書いてあると思いますので、一読することをお勧めします。型とサイズが分かれば、自ずと対応するC++の型が推測できるようになります。

コード:
using System;
using System.Text;
using System.Runtime.InteropServices;

class Class1 {
	// byte[]で受ける
	[DllImport("MyDll")]
	public static extern uint GetValue(byte[] lpResponse, uint dwLen, ref uint lpdwReadLen);

	// 文字列で受ける
	[DllImport("MyDll", EntryPoint="GetValue")]
	public static extern uint GetString(StringBuilder data, uint dwLen, ref uint lpdwReadLen);


	[STAThread]
	static void Main(string[] args) {
		uint ret = 0;
		uint len = 0;
		byte[] data = new byte[128];

		ret = GetValue(data, (uint)data.Length, ref len);
		// byte[]を文字列に変換
		Console.WriteLine(Encoding.Default.GetString(data, 0, (int)len));

		// 文字列だと分かっているのなら
		// 最初からStringBuilderで受けることも出来る
		StringBuilder str = new StringBuilder(128);
		ret = GetString(str, (uint)str.Capacity, ref len);
		Console.WriteLine(str.ToString());	
	}
}


Pluto
常連さん
会議室デビュー日: 2002/07/01
投稿数: 40
投稿日時: 2004-12-20 23:16
mei さん、返信ありがとうございます (感謝)。


それで、もう少しご教示をお願いしたいのですが、

// 文字列だと分かっているのなら
// 最初からStringBuilderで受けることも出来る

という内容についてですが、文字列と分かっていて、
byte の配列で受け取る場合と、StringBuilder で
受け取る場合とでは、動作上違いはあるのでしょうか?
(Encoding の差なのでしょうか?)


mei さんからの

「自ずと対応するC++の型が推測できるようになります。」

なれるように、日々精進させていただきます (感謝)。
今後とも宜しくお願いします。




mei
大ベテラン
会議室デビュー日: 2003/04/08
投稿数: 114
投稿日時: 2004-12-20 23:50
こんばんは、meiです。

引用:

Plutoさんの書き込み (2004-12-20 23:16) より:

それで、もう少しご教示をお願いしたいのですが、

// 文字列だと分かっているのなら
// 最初からStringBuilderで受けることも出来る

という内容についてですが、文字列と分かっていて、
byte の配列で受け取る場合と、StringBuilder で
受け取る場合とでは、動作上違いはあるのでしょうか?
(Encoding の差なのでしょうか?)



例えば、byte[]の内容が画像データだったりすると、StringBuilderで文字列として受けても意味を成さない内容になってしまう、くらいの意味でした。Windowsなら文字列ならStringBuilderで受けておけば、SJIS(Unicodeも可かな?)ならエンコーディングしてくれるのでほとんど問題にならないと思います。

余談ですが、Mono(オープンソースな.NET互換環境)などで実行するとUTF-8としてエンコーディングされてしまい、(Windows上では)目的の内容にならなかったりします。こういう場合は、byte[]で無変換で受け取って自力でエンコーディングといった使い方をしたりします。
Pluto
常連さん
会議室デビュー日: 2002/07/01
投稿数: 40
投稿日時: 2004-12-21 11:27
mei さん、度々返信ありがとうございます。

拙者、未熟者ですが、今後ともご指導の程、宜しくお願いします。
1

スキルアップ/キャリアアップ(JOB@IT)