主筆プラグインの開発について
[1] 主筆嬢 05/11/01 20:09
最近気がついたんだけど、この「主筆」のプラグインって、すごく作りにくい。
なんとかしろ。
[2] nabiki_t 05/11/01 20:35
んなことはない。気のせいだ。
[3] 主筆嬢 05/11/01 21:15
絶対気のせいなんかじゃない。
だって、引数に与えられた関数ポインタにパラメタ渡して、関数ポインタ取得してその関数ポインタを呼び出すだなんて、絶対におかしい。人のことを馬鹿にしてるのか。
ユーザビリティ最悪。
[4] nabiki_t 05/11/01 22:06
自分の頭が悪いのを棚に上げて文句を言うな。
[5] 主筆嬢 05/11/01 22:45
うるさい。
インターフェースの作りが悪いんだ。
[6] nabiki_t 05/11/01 23:32
しかしまぁ、まじめな話、インタフェースがあまりよろしくないのは、認めざるを得まい。
と言うことで、こんなんラッパクラスを作ってみた。
spf.h 10.3KB
ついでに、これも
PluginFuncID.h 3.2KB
[7] 匿名希望 05/11/02 02:28
馬鹿二人が罵りあっているようにしか見えない……
[8] 主筆嬢 05/11/02 06:33
仕様書とか無いの?
[9] nabiki_t 05/11/02 19:17
無い。これぐらい自分でソース読め。
でも一応使い方を示しておく。
#include "spf.h"
using namespace std;
extern "C" void foo( PFT_GetAPIFunction GetAPIFunction )
{
CSyuhituPlugin csp( GetAPIFunction );
try {
csp.ShowInformationMsgBox( L"メッセージ" );
}
catch( CSP_Err r ) {
printf( "ERROR %d\n", r.LastFunction );
}
}
|
まぁ、まずはspf.hというヘッダファイルをインクルードする必要がある。
で、一部stringやwstringを使ってる部分があるから、必要に応じて、デフォルトでstdの名前空間を使用することを宣言しておく。まぁ、上記の例では必要ないがな。
次に、呼ばれた関数内(ここではfoo)で、CSyuhituPluginクラスのインスタンスを生成する。そのときに、引数として渡された関数ポインタを、コンストラクタに指定する。
CSyuhituPlugin csp( GetAPIFunction );
|
後は必要に応じてCSyuhituPluginクラスのメンバを呼び出してやればいい。各メンバ関数はAPI関数と1対1で対応しているから、まぁ、悩むことはないだろう。
csp.ShowInformationMsgBox( L"メッセージ" );
|
あぁ、あと、なんか問題が発生したときには、CSP_Errというオブジェクトが例外として投げられるから、ちゃんとtryブロックが囲んでお入れやった方がいい。そうしないと、例外が発生したときに「主筆」のプロセスが落ちることになる。
[10] 主筆嬢 05/11/02 20:38
ふーん。
まぁ、「一旦関数ポインタを取得する」という手間は省けるかな。
[11] 主筆嬢 05/11/02 20:45
そういえば、>>9のソースの「extern "C"」てなにさ。
[12] nabiki_t 05/11/02 21:23
そりゃ、あれだ。
当然だが、このコードは必ずC++でコンパイルしなきゃならない。でも、そうすると関数名がマングリングされて、「主筆」側から呼び出すことが出来なくなってしまう。
だから、「extern "C"」と記述して、Cのリンケージ規約に従うように宣言するひつようがある。
これは余談だが、もしかしたらプラグイン設定ファイルの呼び出し先関数名に、マングリングを考慮した名前を記述してやれば、呼び出すことが出来るかも知れない。もっとも、そんなことをしなければならない必要性もメリットも無いけどな。
[13] 広告 05/11/02 21:42
[14] 主筆嬢 05/11/02 23:42
こんなプログラムを作って、
#include "PluginFuncID.h"
void foo( PFT_GetAPIFunction GetAPIFunction )
{
PFT_ShowInformationMsgBox pF =
(PFT_ShowInformationMsgBox)GetAPIFunction( PFID_SHOWINFORMATIONMSGBOX );
pF( L"あいうえお" );
}
こんなコマンドでコンパイルしてみたんだけど、
cc -G -o test1.so test1.c
なんか、こんなメッセージが表示されて実行出来ないんだけど。

何とかしろ。
[15] nabiki_t 05/11/02 23:58
>>14
態度でかいな、おまえ。
[16] 名無しさん 05/11/03 00:01
>>15
糞なモンを作る香具師が悪い。
[17] nabiki_t 05/11/03 08:14
>>14
そりゃ、コンパイルの仕方が悪いんだ。
「主筆」の本体は64bitでコンパイルしてある。だが、おまいのコンパイルの仕方だと「test1.so」は32bitのバイナリになる。
Solarisの仕様上、64bitと32bitのオブジェクトモジュールをリンクすることは出来ないから、64bitの「主筆」から32bitの「test1.so」を呼び出そうとすると、失敗する。
だから、SunCCを使ってるんなら、こういう風にコンパイルする必要がある。
cc -xarch=v9 -G -o test1.so test1.c
[18] ぬるぽ 05/11/03 08:37
ぬるぽ
[19] ぬるぽ 05/11/03 09:02
>>18 ガッ
[20] 主筆嬢 05/11/03 11:37
今度はこんなプログラムを作ったんだけど、
#include "PluginFuncID.h"
void foo( PFT_GetAPIFunction GetAPIFunction )
{
PFT_ShowInformationMsgBox pF =
(PFT_ShowInformationMsgBox)GetAPIFunction( PFID_SHOWINFORMATIONMSGBOX );
wchar_t *p = (wchar_t*)malloc( sizeof( wchar_t ) * 100 );
wscpy( p, L"あいうえお" );
pF( p );
free( p );
}
このプラグインを呼び出すと、wscpyのところでプロセスが落ちるんですが。
なんか、mallocでトンチンカンなアドレスが返されるように見えるんですが。
[21] 匿名希望 05/11/03 11:57
そりゃ、おまえの脳みそがトンチンカンだからだろう。
[22] nabiki_t 05/11/03 12:16
>>20
詳しいことは知らないが、どうやらいくつかのヘッダファイルをインクルードしていないのが原因のようだ。
特にmallocは、ヘッダファイル内でdefineされたもので、本当は違う名前らしい。だから、ちゃんとヘッダファイルをインクルードしないと、mallocと言う名前のなんだかよく判らない関数を呼び出すのか、どっか不正なアドレスを呼び出すのかは知らないが、なんかよく判らないアドレスが帰ってくることになる。
だから、上記のプログラムなら、PluginFuncID.h以外に少なくとも<stdlib.h>と<wchar.h>ぐらいはインクルードしなくてはならないはずだ。
[23] 主筆嬢 05/11/03 14:12
主筆の第12版で、PFID_SETCHARの関数を呼んでも、常に偽が帰ってきて、何もおきないんですが。
[24] nabiki_t 05/11/03 14:25
実は、第12版ではSetCharは実装していない。
何もせずPFT_FALSEを返すようになっている。
[25] 主筆嬢 05/11/03 14:31
バグじゃん。
[26] nabiki_t 05/11/03 14:35
バグではありません。仕様です。
なお、第13版でこの仕様は変更される予定です。
[27] 名無しさん 05/11/03 14:48
>>26
DQN Sヨは4ネ
[28] 主筆嬢 05/11/03 15:21
プラグインから、テキストの追加や削除をしたいんだけど、APIにInsertとかDeleteとか無いの?
[29] 広告 05/11/03 15:55
[29] nabiki_t 05/11/03 16:20
>>28
テキストの追加や削除にはReplaceを使う。
追加するときは、
PFT_Replace Replace = (PFT_Replace)GetAPIFunction( PFID_REPLACE );
unsigned long LP = 挿入位置の行;
unsigned long CP = 挿入位置のカラム;
Replace( LP, CP, LP, CP, L"挿入する文字列" );
と、する。
つまり、置換対象の範囲の長さが0ならば、単純な挿入になる、ということ。
削除するなら、
PFT_Replace Replace = (PFT_Replace)GetAPIFunction( PFID_REPLACE );
unsigned long SLP = 削除開始位置の行;
unsigned long SCP = 削除開始位置のカラム;
unsigned long ELP = 削除終了位置の行;
unsigned long ECP = 削除終了位置のカラム;
Replace( SLP, SCP, ELP, ECP, L"" );
と、する。
つまり、置換後の文字列として、長さ0の文字列を指定すれば、単純な削除になる、ということ。
[30] 主筆嬢 05/11/17 20:42
第13版でようやくSetCharが実装されたっていうから、こういうプログラムを作ってみた。
void goo( PFT_GetAPIFunction GetAPIFunction )
{
PFT_GetLineCount GetLineCount =
(PFT_GetLineCount)GetAPIFunction( PFID_GETLINECOUNT );
PFT_GetCharCount GetCharCount =
(PFT_GetCharCount)GetAPIFunction( PFID_GETCHARCOUNT );
PFT_SetChar SetChar =
(PFT_SetChar)GetAPIFunction( PFID_SETCHAR );
unsigned long LP, CP;
unsigned long LineCnt;
unsigned long LineLen;
if ( !GetLineCount( &LineCnt ) )
printf( "ERROR GetLineCount\n" );
for ( LP = 0; LP < LineCnt; LP++ ) {
if ( !GetCharCount( LP, &LineLen ) )
printf( "ERROR GetCharCount LP = %d\n", LP );
for ( CP = 0; CP < LineLen; CP++ ) {
if ( !SetChar( LP, CP, L'-' ) )
printf( "ERROR SetChar LP = %d CP = %d\n", LP, CP );
}
}
}
で、こういうデータでこのプラグインを動かしてみた。
そしたら、こういう結果になって、

コンソールにはこういう風に表示された。

私としては、全部の文字が'-'になることを期待していたんだけど。
バグってんじゃないの?
[31] nabiki_t 05/11/03 20:45
あぁ、確かにバグってるな。
[34] 主筆嬢 05/11/17 20:47
やっぱバグかよ。
てめぇ、ざけるなよ。
[32] nabiki_t 05/11/03 20:48
おまえのプログラムがバグってるんだ。馬鹿。
行末には改行コードがあるんだ。だから、行末の文字にSetCharしたら改行コードが削除されて、その次の行と連結されるんだ。
つまり、絵で描くとこういう事だ。
下記の状態が、まだSetcharする前の状態だ。

この状態から、赤い所に対してSetCharして'-'を置いたとする。
するとこうなる。

ここでだ。おまえのプログラムでは、行末の\nを-に置き換えた後、次の行を処理するべく、LPに1を足してCPを0にしているだろう? ところが、おまえが考えていた「次の行」は、前の行に連結されちゃって、実際には「その次の行」が来ているわけだ。
その上、行数も減っている。だから、最初予測していた行数回だけLP++をすると、存在しない行に対してGetCharCountをする羽目になる。
と言うことで、おまえのプログラムの実行結果はあれで正しいわけだ。
[33] 主筆嬢 05/11/17 20:50
なんか厭な仕様だな。
[34] nabiki_t 05/11/03 20:52
文句言うな。
ついでに言うと、一番最後の行には、改行コードは存在しないから、そのつもりでな。
[35] 主筆嬢 05/11/17 20:55
ふーん。
|