DLLの作成に挑戦

アバター
a5ua
記事: 199
登録日時: 14年前

DLLの作成に挑戦

投稿記事 by a5ua » 14年前

以前公開したタイピングゲーム用ライブラリのDLLバージョンを公開します。

要望もあったので、これを機にDLLの作り方を勉強してみようと思い、作成しました。
他の環境で動くかわからないので、動作確認をしてくださると嬉しいです。

【DLLのダウンロード】(ヘッダファイル&インポートライブラリ同梱)

[拡張子 zip は無効化されているため、表示できません]

上のファイルにはDLLを作成するためのプロジェクトファイルも入っています。
ビルドには、このライブラリが必要となっています。

【a5ua C++ libraries】

[拡張子 zip は無効化されているため、表示できません]

ヘッダファイル(APIの定義)の内容とサンプルプログラムを載せておきます。
各APIはWINAPI風にハンドルを用いてアクセスします。

【a5ua/typing_engine_dll.h】

CODE:

#pragma once

#ifdef A5UA_TYPING_ENGINE_DLL_EXPORT
#	define A5UA_TYPING_ENGINE_DLL_API __declspec(dllexport)
#else
#	define A5UA_TYPING_ENGINE_DLL_API __declspec(dllimport)
#endif

#ifndef __cplusplus
#include 
#endif

// タイピングエンジンのハンドル定義
typedef struct a5uaHTYPING_ {int unused;} *a5uaHTYPING;

// 入力状況を取得するときに指定するパートを表す列挙型の定義
enum A5UA_TYPING_PROGRESS
{
	A5UA_TYPING_PROGRESS_ACCEPTED,	// 受理された部分
	A5UA_TYPING_PROGRESS_TARGET,	// 現在入力しようとしている部分
	A5UA_TYPING_PROGRESS_REMAINDER  // まだ入力されていない部分
};

// タイピングエンジンAPIの定義
#ifdef __cplusplus
extern "C" {
#endif

	// タイピングエンジンの作成
	// [in] path 設定ファイルのパス
	// [ret] タイピングハンドル(設定ファイルが読み込めないなど、エラーが発生した場合はNULLポインタを返す)
	A5UA_TYPING_ENGINE_DLL_API
	a5uaHTYPING a5uaTypingCreateTyping(const char *path);

	// タイピングエンジンの破棄
	// [in] hTyping タイピングハンドル
	A5UA_TYPING_ENGINE_DLL_API
	void a5uaTypingDestroyTyping(a5uaHTYPING hTyping);

	// タイプする文字列の設定
	// [in] hTyping タイピングハンドル
	// [ret] 成功したかどうかの真偽値
	A5UA_TYPING_ENGINE_DLL_API
	int a5uaTypingSetWord(a5uaHTYPING hTyping, const wchar_t *word);

	// 一文字入力する
	// [in] hTyping タイピングハンドル
	// [ret] 入力を受理したかどうかの真偽値
	A5UA_TYPING_ENGINE_DLL_API
	int a5uaTypingInput(a5uaHTYPING hTyping, wchar_t c);

	// 設定文字列部分の入力状況を取得
	// [in] hTyping タイピングハンドル
	// [in] part A5UA_TYPING_PROGRESS 列挙型の値を指定する
	// [ret] 入力に応じた部分文字列
	A5UA_TYPING_ENGINE_DLL_API
	const wchar_t *a5uaTypingGetWordProgress(a5uaHTYPING hTyping, int part);

	// ローマ字部分の入力状況を取得
	// [in] hTyping タイピングハンドル
	// [in] part A5UA_TYPING_PROGRESS 列挙型の値を指定する
	// [ret] 入力に応じた部分文字列
	A5UA_TYPING_ENGINE_DLL_API
	const wchar_t *a5uaTypingGetInputProgress(a5uaHTYPING hTyping, int part);

	// 設定した文字列をタイプし終わったかどうかの判定
	// [in] hTyping タイピングハンドル
	// [ret] 終わったかどうかの真偽値
	A5UA_TYPING_ENGINE_DLL_API
	int a5uaTypingFinished(a5uaHTYPING hTyping);

#ifdef __cplusplus
}
#endif
【main.c】

CODE:

// Visual Studio なら、これでリンク可能
// 対応するDLLファイルは、EXEファイルから見えるところにおいてください

#ifdef _MT
#	ifdef _DLL
#		pragma comment(lib, "a5ua_typing_engine_dll-md.lib")
#	else
#		pragma comment(lib, "a5ua_typing_engine_dll-mt.lib")
#	endif
#endif

#include 
	
#include 
#include 

void PrintWordProgress(a5uaHTYPING hTyping)
{
	const wchar_t *a = a5uaTypingGetWordProgress(hTyping, A5UA_TYPING_PROGRESS_ACCEPTED);
	const wchar_t *t = a5uaTypingGetWordProgress(hTyping, A5UA_TYPING_PROGRESS_TARGET);
	const wchar_t *r = a5uaTypingGetWordProgress(hTyping, A5UA_TYPING_PROGRESS_REMAINDER);
	printf("[%S](%S)\n", a, r);
	printf("[%S]{%S}\n", a, t);
}

void PrintInputProgress(a5uaHTYPING hTyping)
{
	const wchar_t *a = a5uaTypingGetInputProgress(hTyping, A5UA_TYPING_PROGRESS_ACCEPTED);
	const wchar_t *t = a5uaTypingGetInputProgress(hTyping, A5UA_TYPING_PROGRESS_TARGET);
	const wchar_t *r = a5uaTypingGetInputProgress(hTyping, A5UA_TYPING_PROGRESS_REMAINDER);
	printf("[%S](%S)\n", a, r);
	printf("[%S]{%S}\n", a, t);
}

void PrintProgress(a5uaHTYPING hTyping)
{
	PrintWordProgress(hTyping);
	PrintInputProgress(hTyping);
	puts("");
}

void Simulate(a5uaHTYPING hTyping, const wchar_t *word, const wchar_t *input)
{
	if (!a5uaTypingSetWord(hTyping, word)) {
		puts("error: ローマ字に変換できません");
	}

	PrintProgress(hTyping);

	for ( ; !a5uaTypingFinished(hTyping) && *input; ++input) {
		if (a5uaTypingInput(hTyping, *input)) {
			PrintProgress(hTyping);
		} else {
			printf("miss!\n");
		}
	}
	if (a5uaTypingFinished(hTyping)) {
		printf("finished!\n\n");
	} else {
		printf("not finished!\n\n");
	}
}

// 設定ファイルのパス
// このファイルには、カナ・記号とローマ字の対応関係が書かれている
#define TYPING_CONFIG_PATH "config.txt"

int main(void)
{
	a5uaHTYPING hTyping;

	// タイピングエンジンの作成
	hTyping = a5uaTypingCreateTyping(TYPING_CONFIG_PATH);

	if (!hTyping) {
		fprintf(stderr, "タイピングエンジンの作成に失敗しました\n");
		return -1;
	}

	// ロケールの設定
	setlocale(LC_ALL, "japanese");

	// いくつかシミュレーション
	Simulate(hTyping, L"あかさたなはまやらわ", L"akasatanahamayarawa");
	Simulate(hTyping, L"テストてすと", L"tesutotest");
	Simulate(hTyping, L"とうきょうとっきょきょかきょく", L"toukixyoutoltukilyokyocakyocu");

	// タイピングエンジンの破棄
	a5uaTypingDestroyTyping(hTyping);

	return 0;
}

アバター
みけCAT
記事: 6734
登録日時: 14年前

RE: DLLの作成に挑戦

投稿記事 by みけCAT » 14年前

とりあえずランタイムライブラリを静的リンクするバージョンはうまく動作したようです。
動的リンクするバージョンは、DLLを使う+本家ライブラリをリンクするということですか?

せっかく作っていただいたのにケチをつけるのは悪いとは思いますが、
本家ライブラリにあったコンフィグ機能は実装されていないのですか?

自分で作ってみたサンプルプログラムを添付しておきます。
Shift-JIS←→Unicodeの変換をして関数を呼び出すラッパーを作って呼び出してみました。
添付ファイル

[拡張子 zip は無効化されているため、表示できません]


アバター
a5ua
記事: 199
登録日時: 14年前

RE: DLLの作成に挑戦

投稿記事 by a5ua » 14年前

みけCAT さん

コメントありがとうございます。一応動作確認ができたということで、よかったです。
みけCAT さんが書きました: 動的リンクするバージョンは、DLLを使う+本家ライブラリをリンクするということですか?
Visual C++では、
コンパイルオプションによって、「標準ライブラリ」のリンク方法が異なります。
そして、外部ライブラリと自分のプログラムでその方法を一致させる必要があるのです。

/MDオプションでは、実行時に、msvcr***.dllなどのファイルが必要です。
【参照】
http://msdn.microsoft.com/ja-jp/library ... 00%29.aspx

公開したライブラリのファイル名に付いている「mt, md」は、上記のコンパイルオプション「/MT, /MD」に対応しています。
「mt, md」のどちらを使うかは、標準ライブラリのリンク方法の違いによって決めるのであって、C++のライブラリ(a5ua_typing_engine.lib)を気にする必要はありません。
(VC以外でのこれらの切り替え方法は、私には分かりません。mtのほうで動いたということは、みけCATさんの環境では、標準ライブラリは静的リンクされているということだと思います。)
みけCAT さんが書きました: 本家ライブラリにあったコンフィグ機能は実装されていないのですか?
コンフィグ機能については、作っておきながら、あまり設計が気に入ってなくて
もう少し改良しようと思っていました。(と言いつつ、放置していました)

今後インターフェースが変更されるような気がするので、DLLの方には提供しませんでした。申し訳ありません。

あと、ゲームに組み込んで使う際に、config.txtが丸見えなのは良くないので、
データをソース中にハードコーディングするなり、簡単な暗号化に対応するなりしたほうがいいんだろうなぁ、と考えています。