[delphi-users:1390] EmEditorのPlugin作成でC++のヘッダをpasにしたい。

63 views
Skip to first unread message

Delフサギコ

unread,
Oct 6, 2010, 7:45:12 AM10/6/10
to delphi...@freeml.com
こんばんは

EmEditorのPluginを作っています。環境はD2007です。

C++のコードとDelphiコードとの連携がわからないので
教えていただきたくメールします。


EmEditorではPlugin.hというものが配布されています。
これを手動変換して、plugin.pasというDelphiで利用できる形にしたものを作っています。

昔は何名かの方がつくられていて配布されていたのでs
私は、それを改良して使っていますが

EmEditorとPlugin.hは更新されるけど、Plugin.pasは放置されたままで
EmEditor ver5や6の機能しか Plugin.pas には取り込めていません。

ここで、C++のヘッダファイルを、どのようにDelphiに取り込めばいいのかが
相当迷っていて、正しいかどうか判断がつかないため教えていただきたいのです。


具体的には正規表現を使ってEmEditorの検索機能を
プラグイン側から使いたいというものです。

Plugin.hにこのような記載がありました。

typedef struct _FIND_REGEX_INFO {
size_t cbSize; // sizeof( FIND_REGEX_INFO )
UINT nFlags;
LPCWSTR pszRegex;
LPCWSTR pszText;
LPCWSTR* ppszStart;
LPCWSTR* ppszEnd;
LPCWSTR* ppszNext;
LPCWSTR pszReplace; // new v9
LPWSTR pszResult; // new v9
UINT cchResult; // new v9
} FIND_REGEX_INFO;


#define EE_FIND_REGEX (EE_FIRST+76)

#ifdef EE_STRICT
inline BOOL Editor_FindRegex( HWND hwnd, FIND_REGEX_INFO* pFindRegexInfo )
{
_ASSERT( hwnd && IsWindow( hwnd ) );
return (BOOL)SNDMSG( (hwnd), EE_FIND_REGEX, (WPARAM)0, (LPARAM)pFindRegexInfo );
}
#else
#define Editor_FindRegex( hwnd, pFindRegexInfo ) \
(BOOL)SNDMSG( (hwnd), EE_FIND_REGEX, (WPARAM)0, (LPARAM)pFindRegexInfo )
#endif

これを、Delphi 言語に置き換えたくて、次のようにしています。
※EESTRICTは常にTrueのようです。

plugin.pasの一部

type _FIND_REGEX_INFO = record
cbSize: Longword ; // sizeof( FIND_REGEX_INFO )
nFlags: Longword;
pszRegex: PWideChar;
pszText: PWideChar;
ppszStart: PWideChar;
ppszEnd: PWideChar;
ppszNext: PWideChar;
end; // FIND_REGEX_INFO;
FIND_REGEX_INFO = _FIND_REGEX_INFO;
TFindRegexInfo = FIND_REGEX_INFO;
PFindRegexInfo = ^TFindRegexInfo;

const EE_FIND_REGEX = (EE_FIRST + 76);
function Editor_FindRegex(hwnd: HWND; pFindRegexInfo: PFindRegexInfo): Boolean;
begin
Result := BOOL( SendMessage(hwnd, EE_FIND_REGEX, 0, UINT(pFindRegexInfo)) );
end;

これでコンパイルは通ります。
定数などは、別の場所で宣言されていたりします。

これを利用して、Delphiのプラグイン側で次のように記述しています。

procedure DuplicationHighlight(hwnd: HWND; const S: WideString);
var
I: Integer;
FindRegexInfo: TFindRegexInfo;
DuplicationText: WideString;
begin
DuplicationText := 'A|B';

FillChar(FindRegexInfo, SizeOf(TFindRegexInfo), 0);
with FindRegexInfo do
begin
cbSize := SizeOf(TFindRegexInfo);
nFlags := 0;
pszRegex := @DuplicationText;
pszText := @S;
end;

LogOutput( IntToStr( Integer( Editor_FindRegex(hwnd, @FindRegexInfo) ) ));

Sにはエディタ上の文字列が入ってきます。
他の関数は正しく動いているので、このあたりには問題がありません。

書き方がわからなかったのでこのようにして試してみても
結果は変わりません。
pszRegex := PWideChar(DuplicationText);
pszText := PWideChar(S);


このようにしても、検索にヒットしようとしまいと
ログには常に1が書き込まれ
どうも動いていないようなのです。

該当メッセージのヘルプはこちらからみれます。
http://jp.emeditor.com/help/plugin/message/ee_find_regex.htm

おわかりになる方、、、、、、
基本的にC++の理解ができていないので、
どこかに間違いがあると思うのですが教えてください。

よろしくお願いします。


そもそも、C++の
_FIND_REGEX_INFO
FIND_REGEX_INFO

この二つの違いの意味がわかりません。

--
Delフサギコ ミ・д・彡 <delfu...@gmail.com>


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
みんなの気になってたアレ、調査しました!
http://ad.freeml.com/cgi-bin/sa.cgi?id=fVZHX
-----------------------------------------------------[freeml by GMO]--

umez

unread,
Oct 6, 2010, 8:56:20 AM10/6/10
to delphi...@freeml.com
こんにちは、梅澤@プロキャストです。

ざっと見ただけなので、外している可能性大ですが... (^ ^;;

C++でなく、Cレベルしか分かりませんが、ご紹介されたヘルプの内容だと、
ppszStart、ppszEnd、ppszNext
の3つは、EmEditor側が呼出側に返してくれる値のように見受けられます。
よって、まずは、「検索結果文字列の開始位置」「検索結果文字列の終了位置」
「次に検索すべき位置」の3つの変数を用意し、その変数のアドレスを、
ppszStart、ppszEnd、ppszNext
に代入しておいてから、呼び出すべきなのではないでしょうか?


また、構造体サイズをセットするタイプの構造体なので、型自体の変化を
内部的にチェックしているとは思いますが、念のため、V9に合せて、
pszReplace、pszResult、cchResult
も追加して、試されてみてはいかがでしょう。


他の関数が正しく動いているなら、アライメントの問題はなさそうですし...

>そもそも、C++の
>_FIND_REGEX_INFO
>FIND_REGEX_INFO
>
>この二つの違いの意味がわかりません。

これに関しては、C言語の時とそれほど変っていないと思うのですが、(間違っ
ていたら済みません。)型名と変数名みたいな感じです。
c++ 構造体
でGoogle検索してみるといくつかヒットします。

また、単なる思いつきですが、EmEditor側は検索結果を構造体に書込んでく
れるだけで、画面上には表示しないという可能性もあるかもしれません。


----------
Tomomi Umezawa um...@procast.co.jp


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
新メンバーを便利な@招待機能で一気に登録しよう!
http://ad.freeml.com/cgi-bin/sa.cgi?id=fWbcz

auemura

unread,
Oct 6, 2010, 9:53:40 PM10/6/10
to delphi...@freeml.com
ども上村です。

type _FIND_REGEX_INFO = record
cbSize: Longword ; // sizeof( FIND_REGEX_INFO )
nFlags: Longword;
pszRegex: PWideChar;
pszText: PWideChar;

ppszStart: PPWideChar;
ppszEnd: PPWideChar;
ppszNext: PPWideChar;
end; // FIND_REGEX_INFO;

ppszStart、ppszEnd、ppszNextはWideCharのポインタのポインタなんで定義は上記のようになるかと。

なんで使うときは
var
pStart: PWideChar;
pEnd: PWideChar;
pNext: PWideChar;

FillChar(FindRegexInfo, SizeOf(TFindRegexInfo), 0);
with FindRegexInfo do
begin
cbSize := SizeOf(TFindRegexInfo);
nFlags := 0;

pszRegex := @@DuplicationText;
pszText := @S;
ppszStart := @pStart;
ppszEnd := @pEnd;
ppszNext := @pNext;
end;

ppszStart、ppszEnd、ppszNextにEmEditor側からそれぞれアドレスを書き込んでくるようなので受け取る変数を用意しておく必要があるかと思います。
関数が上手くいってなかったのは、0クリアして受け取るアドレスを設定してない為かと。

--
上村 aue...@zeus.eonet.ne.jp

MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
練習の予定も共有スケジュールに登録しよう!
http://ad.freeml.com/cgi-bin/sa.cgi?id=fWhRs

umez

unread,
Oct 6, 2010, 10:13:29 PM10/6/10
to delphi...@freeml.com
こんにちは、梅澤@プロキャストです。

なるほど、Start, End, Next が書かれる実際のメモリ領域は、EmEditor側で
確保して、そのアドレスを3つのフィールドで返してくれるので、「その
アドレスを受け取るための変数」のアドレスを、呼出側が渡してやる必要が
ある、という事ですね。

領域の確保自体は、呼び出し側でやるものと思ってました。

----------
Tomomi Umezawa um...@procast.co.jp


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
ちょっとした連絡に♪メンバー掲示板を有効活用しよう!
http://ad.freeml.com/cgi-bin/sa.cgi?id=fWiiP

Delフサギコ

unread,
Oct 6, 2010, 11:45:33 PM10/6/10
to delphi...@freeml.com
梅澤さん、上村さん、ありがとうございます。

2010年10月7日10:53 auemura


> type _FIND_REGEX_INFO = record
> cbSize: Longword ; // sizeof( FIND_REGEX_INFO )
> nFlags: Longword;
> pszRegex: PWideChar;
> pszText: PWideChar;
> ppszStart: PPWideChar;
> ppszEnd: PPWideChar;
> ppszNext: PPWideChar;
> end; // FIND_REGEX_INFO;
>
> ppszStart、ppszEnd、ppszNextはWideCharのポインタのポインタなんで定義は上記のようになるかと。

なるほど、そうなんですね。
ポインタのポインタ...ですか。

ポインタを参照渡しするイメージなんですかね・・・
難しいです。

pStart: PWideChar;
pEnd: PWideChar;
pNext: PWideChar;

と、宣言しておき

ppszStart := @pStart;
ppszEnd := @pEnd;
ppszNext := @pNext;

このようにすることで、動作しました。


> pszRegex := @@DuplicationText;
> pszText := @S;

この2行がまだよくわからないのですが

pszRegex := PWideChar(DuplicationText);
pszText := PWideChar(S);

でも動いているようなのですが、それじゃよくないのでしょうか。

文字列のアドレスを渡すのとポインタを渡すのと
一緒なのかな?

> 関数が上手くいってなかったのは、0クリアして受け取るアドレスを設定してない為かと。

そのようですね。

ありがとうございます。

typedefについては
こちらを読みました。

typedef structとstructの違い
http://hpcgi3.nifty.com/mmgames/patio/patio.cgi?mode=view&no=1695

Re: typedef structとstructの違い ( No.3 )
の、(2)の項目でしたね。

とても勉強になりました。
ありがとうございます。


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
学園祭で撮った写真をMLにアップしよう!
http://ad.freeml.com/cgi-bin/sa.cgi?id=fWjHF

auemura

unread,
Oct 6, 2010, 11:50:55 PM10/6/10
to delphi...@freeml.com
> なるほど、Start, End, Next が書かれる実際のメモリ領域は、EmEditor側で
> 確保して、そのアドレスを3つのフィールドで返してくれるので、「その
> アドレスを受け取るための変数」のアドレスを、呼出側が渡してやる必要が
> ある、という事ですね。
>
> 領域の確保自体は、呼び出し側でやるものと思ってました。

ども、上村です。

想像で書いてますが、おそらくStart,End,Nextで返ってくるアドレスはpszTextの中のいずれかの文字のアドレスだと思います。
なんで、EmEditor側で何らかのメモリを確保してるって事はないんじゃなかろうかと。

ヘルプみても、解放処理呼ぶ事なんて記述もありませんでしたし。

-- 
上村

MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
ゆるくて新しい農場ライフ♪ベジモンたちが待ってるよ!
http://ad.freeml.com/cgi-bin/sa.cgi?id=fWjNQ

umez

unread,
Oct 6, 2010, 11:59:31 PM10/6/10
to delphi...@freeml.com
こんにちは、梅澤@プロキャストです。

なるほど。最初に Start,End等は、Index的なものが入るものかと思い込ん
でいたのですが、それがなぜ「文字列形式で?」と思っていました。
これでスッキリです。

auemura <delphi...@freeml.com> さんは書きました。<2010/10/07>

----------
Tomomi Umezawa um...@procast.co.jp


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
みんなの気になってたアレ、調査しました!
http://ad.freeml.com/cgi-bin/sa.cgi?id=fWjYT

Reply all
Reply to author
Forward
0 new messages