秀丸の正規表現用DLLをDelphiから使いたい

このQ&Aのポイント
  • 秀丸に同梱されている正規表現処理用DLL、HMJRE.DLLをDelphiで使用しようとしていますが、うまくいきません。
  • 実行しようとすると「エントリーポイントが見つかりません」と表示されます。
  • DelphiのバージョンはXE5です。
回答を見る
  • ベストアンサー

秀丸の正規表現用DLLをDelphiから使いたい

秀丸に同梱されている正規表現処理用DLL、HMJRE.DLLをDelphiで使用しようとしているのですが、 うまくいきません。 実行しようとすると「エントリーポイントが見つかりません」と表示されます。 ---------------------- function dllfuncstr(func:String;find_str:String;target_str:String;start_pos:Integer;replace_str:String;kind:Integer):String; external 'HMJRE.DLL'; ... procedure TForm1.Button1Click(Sender: TObject); var find_str, target_str, replace_str:String; start_pos, kind:Integer; begin find_str := '123'; target_str := Memo1.Lines[0]; start_pos := 0; replace_str := 'abc'; kind := 1;// Memo2.Lines[0]:= dllfuncstr('ReplaceRegularNoCaseSence',find_str,target_str,start_pos,replace_str,1); end; ----- 秀丸のヘルプにマクロから呼び出す場合の例 が次のように記載されています。 $s = dllfuncstr( "ReplaceRegular", "([a-z]+)([0-9]+)", "--abcdefg1234567--", 0, "\\2\\1" ); message $s; DelphiのバージョンはXE5です。

質問者が選んだベストアンサー

  • ベストアンサー
  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

>実行しようとすると「エントリーポイントが見つかりません」と表示されます。 HMJRE.DLLにdllfuncstr()でエクポートされているエントリはありませんから当然でしょうね。 >秀丸のヘルプにマクロから呼び出す場合の例 が次のように記載されています。 秀丸のマクロの機能としてdllfuncstr()があるのであって、HMJRE.DLLにdllfuncstr()があるわけではありません。 「Delphi DLL 使い方」辺りで検索してみましょう。 手元にDelphi環境があるワケではないので未確認にはなりますが… function ReplaceRegularNoCaseSence(ReplaceRegular:String, Pattern:String, index:Integer, Replace:String, Action:Integer): String; stdcall; external 'HMJRE.DLL' name 'ReplaceRegularNoCaseSence'; ってな感じになるかと。

kihonkana
質問者

お礼

ありがとうございます。 Delphiの標準ライブラリを使うことにしました。

kihonkana
質問者

補足

回答ありがとうございます。 エラーは出なくなったのですが、 実行すると、Window画面を表示せず終了してしまいます。 uses ... function ReplaceRegularNoCaseSence(ReplaceRegular:String; Pattern:String; index:Integer; Replace:String; Action:Integer): String; stdcall; external 'HMJRE.DLL' name 'ReplaceRegularNoCaseSence'; (区切り文字を「,」から「;」に修正しています) ... procedure TForm1.Button1Click(Sender: TObject); var ReplaceRegular, Pattern, Replace :String; index, Action:Integer; begin ReplaceRegular := '123'; Pattern := '12'; index := 0; Replace := 'abc'; Action := 1;// Label3.Caption := ReplaceRegularNoCaseSence(ReplaceRegular, Pattern, index, Replace, Action);//ここをコメントにするとWindow画面は表示されます end;

その他の回答 (1)

回答No.2

ReplaceRegularNoCaseSense関数の定義は次のようになります。 /// <summary> /// 特定の文字列から特定の正規表現パターンのマッチングをして、ヒットした場合はパラメータに従った置換を実行し、その置換した結果の文字列を返します。 /// </summary> /// <param name="pszPattern"> /// 検索したい正規表現文字列 /// </param> /// <param name="pszTarget"> /// 検索対象の文字列 /// </param> /// <param name="iStart"> /// 検索を開始する桁位置 /// </param> /// <param name="pszReplace"> /// 検索でヒットした文字列を置換する用の文字列 /// </param> /// <param name="iMode"> /// 最初にヒットした文字を置換、1.ヒットしたすべての文字を置換 /// </param> /// <returns> /// 置換した結果の文字列 /// </returns> function ReplaceRegularNoCaseSense(pszPattern: PAnsiChar; pszTarget: PAnsiChar; iStart: Integer; pszReplace: PAnsiChar; iMode: Integer): PAnsiChar; stdcall; external 'HMJRE.DLL' name 'ReplaceRegularNoCaseSense'; ReplaceRegularNoCaseSense関数の使用例です。 procedure TForm1.Button1Click(Sender: TObject); var S: AnsiString; begin S := ReplaceRegularNoCaseSense( PAnsiChar('([a-z]+)([0-9]+)'), // 検索したい正規表現文字列 PAnsiChar('--abcdefg1234567--'), // 検索対象の文字列 0, // 検索を開始する桁位置 '\2\1', // 検索でヒットした文字列を置換する用の文字列 1 // 0.最初にヒットした文字を置換、1.ヒットしたすべての文字を置換 ); Memo1.Lines.Add(S); end; 正規表現を使用したいのであれば、標準ライブラリのTRegExを使う方が簡単ですよ。

kihonkana
質問者

お礼

ありがとうございます。 Delphiの標準ライブラリを使うことにしました。

kihonkana
質問者

補足

回答ありがとうございます。 「文字列の暗黙のキャスト...」という警告は出ますがコンパイルは成功しているのに、Window画面が出ません。 unitの内容は以下の通りです。 ----- unit ProTest4Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls; function ReplaceRegularNoCaseSence(ReplaceRegular:String; Pattern:String; index:Integer; Replace:String; Action:Integer): String; stdcall; external 'HMJRE.DLL' name 'ReplaceRegularNoCaseSence'; type TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); private { Private 宣言 } public { Public 宣言 } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var S: AnsiString; begin S := ReplaceRegularNoCaseSence( PAnsiChar('([a-z]+)([0-9]+)'), // 検索したい正規表現文字列 PAnsiChar('--abcdefg1234567--'), // 検索対象の文字列 0, // 検索を開始する桁位置 '\2\1', // 検索でヒットした文字列を置換する用の文字列 1 // 0.最初にヒットした文字を置換、1.ヒットしたすべての文字を置換 ); Memo1.Lines.Add(S); end; end. ----- >正規表現を使用したいのであれば、標準ライブラリのTRegExを使う方が簡単ですよ。 秀丸で作った正規表現がそのまま使えて便利なのではと思ったのです。 (アプリによって正規表現が少し違うというようなことがどこかのサイトに書かれていました) もう少し、他の方の回答を待って、標準ライブラリの使用も検討してみます。

関連するQ&A

  • Delphi6でVB.NETで作成のDLL呼出

    VisualSutudio2005で作成され提供されているDLLをDelphi6から呼びだしたいと思っています。 提供ファイルとしてあるのは以下のものです。 ・DLLファイル本体 ・XMLファイル 直接は呼びだせない(?)と思ったので、 VB.NETでDLLを作って間に入れて、 下のように呼び出せばいいのかなと考えています。 Delphi6で作成のEXE → VB.NETで作成のDLL(COM登録?) → 対象のDLL まずはDelphi6のEXE→VB.NETのDLLの部分を作って試してみたですが Delphi6のEXEの起動時にエラーとなってしまいます。 「アプリケーションの初期化に失敗しました」 ネットなどで調べてみて作り方は下記のようにしました。 <呼ばれる側:VB.NETのDLL> 1.COMクラスを作る。   ・COM参照可能の設定にした。 (タイプライブラリが作成され、レジストリへのCOM登録は自動でされる?) 2.作成したDLLはCドライブ直下に置いた。 ※下の*****は自動作成された固定値が入っています。  また見やすくするためここでは半角空白を全角空白に変えています。 -------------------------------------------------------------------- Imports System.Windows.Forms <ComClass(Middle_Dll.ClassId, Middle_Dll.InterfaceId, Middle_Dll.EventsId)> _ Public Class Middle_Dll #Region "COM GUID"   ' これらの GUID は、このクラスおよびその COM インターフェイスの COM ID を   ' 指定します。この値を変更すると、   ' 既存のクライアントはクラスにアクセスできなくなります。   Public Const ClassId As String   = "**************************"   Public Const InterfaceId As String = "**************************"   Public Const EventsId As String  = "**************************" #End Region   ' 作成可能な COM クラスにはパラメータなしの Public Sub New() を指定しなければ   ' なりません。これを行わないと、クラスは COM レジストリに登録されず、   ' CreateObject 経由で   ' 作成できません。   Public Sub New()     MyBase.New()   End Sub   Public Sub DispMsg()     Dim MsgRet As MsgBoxResult     MsgRet = MessageBox.Show("VB.NET DLLより表示!", "確認メッセージ", MessageBoxButtons.YesNo, MessageBoxIcon.Information)   End Sub End Class --------------------------------------------------------------------- <呼び出し側:Delphi6のEXE> 1.タイプライブラリの取り込み設定で登録したDLLを選択し、   「コンポーネントラッパーの作成」にチェックを入れてインストールを実行。 --------------------------------------------------------------------- unit Unit1; interface uses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls,OleCtnrs,ComObj, OleServer; type  TForm1 = class(TForm)   Button1: TButton;   Edit1: TEdit;   procedure Button1Click(Sender: TObject);  private   { Private 宣言 }  public   { Public 宣言 }  end; var  Form1: TForm1;  //----------  //静的呼出  //----------  procedure DispMsg();Stdcall; external 'c:\Middle_Dll.dll' name 'DispMsg'; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin  //----------  //静的呼出  //----------  DispMsg(); end; end. ----------------------------------------------------------------- Delphi6のEXEはすでにあるものなので、 呼び出し元はDelphi6から変えられませんが、 呼び出し先はC#やC++でも構いません。 (1)Delphi6のEXE→VB.NETのDLLの呼び出しは可能でしょうか? (2)可能でしたら不具合と思われる箇所はどこでしょうか? (3)この方法より良いと思われる方法はありますでしょうか? DLLを作った事がないので見よう見まねで作っています。 気になる点やアドバイス程度でも構いませんので、 どうかよろしくお願いいたします。 == 開発環境 == WindowsXP SP3 Delphi6 Enterprise SP2 VisualSutudio2005 ProffesionalEdition 評価版 .NET Framework 1.1~3.5

  • Delphi XE5をアップデートしたら(2)

    前回アップデートしたら例外処理がおかしくなったという質問をしましたが、 あれから、いろいろやっていたら、exeファイルから実行すると正常にエラーメッセージが出て、RAD Studioから実行すると(デバッグモード?)、ShowMessageのエラーメッセージが出ないことがわかりました。 もしかしたらupdateは関係ないかもわかりません。 (今となっては検証しようがありません) でも、これってデバッガモード(?)の正常な動作なんでしょうか? //前回の質問 Delphi Xe5 Starterを使っています。 今日update2をインストールしたら、動作がおかしくなりました。 プログラムは次の通りです。 ------------------------------------------------- procedure TForm1.TestDoButtonClick(Sender: TObject); var Rep, pattern: string; begin pattern := FindEdit.Text; Rep := ReplaceEdit.Text; try Memo2.Lines.Text := TRegEx.Replace(Memo1.Lines.Text, pattern, Rep, []); except ShowMessage('正規表現にエラーがあります'); end; end; ---------------------------------- たしか、アップデートする前には正規表現にエラーがあれば、「正規表現にエラーがあります」が表示されたはずですが、システム?のエラー表示が出て、プログラムが停止します。 どこか間違ってますか?

  • シフトJIS文字列の中から

    (string str;) pos=str.find_last_of("「"); で2バイトさがそうとしても文字化けと同じように間違った文字を見つけてしまいます このシフト文字列対策はどうすればいいのでしょうか?

  • AccessVBAからC言語のDLLの呼び出し方

    初心者です。はじめまして お世話になります。 概要:C言語で作成したDLLをVBAで呼び出す。 タイトルの通り、C言語で作成したDLLをVBAで呼び出したいのですが、うまく 呼び出すことができず、「エラー番号:49 DLLを正しく呼び出せません。」 というエラーが返ってきてしまいます。 DLLの作成手順もしくはDLLの呼び出し方でおかしな所があればご指摘頂けない でしょうか? C言語のDLL、作成手順は以下の通りです。 DLL作成環境:Visual C++ 6.0 DLL作成手順----------------------------------------- (1)プロジェクトをDLL用に作る  新規作成→プロジェクト→Win32 Dynamic-Link Library→空のDLLプロジェ クト (2)ファイル追加  ソースファイル+すべてのヘッダファイルを追加 (3)DLLを出力対象の関数に「_declspec(dllexport)」をつける 例)------------------------------------- _declspec(dllexport) short dlltest (char *str1, char *str2) --------------------------------------- (4)char を unsigned char へ変換する(/J コンパイルオプション) (5)プロジェクトをデバッグモードからリリースモードに切り替える (6)ビルド実行 (7)「Release」配下に.dllとlibができる。 -作成手順完----------------------------------------------------- 実際のVBAのDLLの呼び出しは以下の通り行っています。 -AccessVBAにてDLLの宣言及び、呼び出し------------------- '呼び出し宣言 Public Declare Function dlltest _ Lib "C:\Project\Dlltest\Release\dlltest.dll" _ (ByVal st1 As String, _ ByVal st2 As String) As Integer 'DLL呼び出し KEKKA = dlltest(string1, string2) -呼び出し完------------------------------------------------ これで実行するとエラーが返されていまいます。 なにぶん、初心者で今回初めてVBAでのプログラミングを行っているので観点 の抜けなどが多分にあると思われます。 どんな小さなことでもご指摘頂けないでしょうか? 宜しくお願い致します。

  • C++DLLからC#へのコールバックに文字列の配列を渡したい

    教えてください! C++のアンマネージドDLLから、複数のファイル名(文字列)をC#に渡したいです。 ステップとしては、 C#から、C++のDLLの関数を最初に呼んで、コールバック関数を渡しています。 次に、DLLからコールバック関数を呼ぶ時に、複数のファイル名を渡したいです。 以下のコードを動かすと、、 C++からは2つ渡しているつもりなのに、 C#ではfilesがサイズ1のString配列として引数に入ってきます。 なぜでしょう? またどうすればC#から複数受け取れるでしょうか? 教えてください! C# public delegate int StringArrayCallback(String[] files); // C# -> C++ public static int start() { StringArrayCallback cb = new StringArrayCallback(onReceivedFiles); int ret = start(cb); return ret; } // C++ -> C# callback public static int onReceivedFiles(String[] files) { return 1; } C++コード typedef int (__stdcall *OnReceivedFilesProc )(char**); int start( OnReceivedFilesProc callback ) { std::string message1_ = "from C++1"; std::string message2_ = "from C++2"; char* messages_[2] = { (char*)message1_.c_str(), (char*)message2_.c_str() }; int ret_ = callback(messages_); std::cout << "[from c#]" << ret_; }

  • 初心者です:指定金額以上の商品だけを表示させるソースがどうしてもわかりません

    プログラミング自体が初心者の者です。 ドスプロンプト画面を表示させ、指定した金額を入力してエンターおすと 指定した金額以上の商品情報だけを元データのCSVファイルから出力させたい内容です。 また、出力は ●二列目:品名 ●三列目:概要 ●四列目:単価 だけを表示させます。CSVには一行ごとにひとつの商品が記載されています。 以下まではできたのですがこのあとどう書いたらよいかわかりません。アドバイスいただけたら助かります。 金額欄はCSVの四列目にあるのですが、この四列目だけをStringからintに変換しないと金額の判定をJavaがわからないんだろうか?と思ったりしますがわかんなくなりました。プログラミングというものは何やら難儀です。。。 ※catch(Exception e)は学習の主題ではないのでこのままで結構です。 ■ファイル1:CSVprac.java ※Tabでインデントしても投稿の確認画面ではインデントが反映されないです。  なんでかな。これではソースがみにくいだろうなぁ。。。投稿完了したらインデントが反映されていると信じて・・・ ------------------------------------------------------ import java.io.*; public class CSVprac { public static void main(String args[]) { String [][] slist = new String [1000][5]; int kibougaku,pos; int gyou; /* 配列の行の変数 */ gyou = 0; int i; String str; try { BufferedReader in = new BufferedReader (new FileReader("syohin.txt")); while((str = in.readLine()) != null) { pos = str.indexOf(','); slist[gyou][0] = str.substring(0,pos); str = str.substring(pos+1); pos = str.indexOf(','); slist[gyou][1] = str.substring(0,pos); str = str.substring(pos+1); pos = str.indexOf(','); slist[gyou][2] = str.substring(0,pos); str = str.substring(pos+1); pos = str.indexOf(','); slist[gyou][3] = str.substring(0,pos); str = str.substring(pos+1); slist[gyou][4] = str; gyou++; } in.close(); BufferedReader br = new BufferedReader (new InputStreamReader(System.in)); System.out.println("何円以上の商品を見ますか?(金額を数字のみで入力ください)"); i = Integer.parseInt(br.readLine()); //ここからがわからない。 System.out.println( ); } catch(Exception e) { System.out.println(e); } } } ------------------------------------------------------ ■ファイル2:syohin.txt ------------------------------------------------------ 3,20型カラーテレビ,テレビ,17550,415 4,20型ステレオカラーテレビ,テレビ,23220,25 5,石油ファンヒーター,冷暖房器,14130,340 7,25型ステレオカラーテレビ,テレビ,34020,610 8,デスクトップパソコン,OA機器,115200,30 10,ノート型パソコン,OA機器,214200,60 12,BS内蔵25型カラーテレビ,テレビ,44820,500 13,230リットル2ドア冷蔵庫,家電,35820,820 14,250リットル3ドア冷蔵庫,家電,53820,540 15,350リットル3ドア冷蔵庫,家電,71820,810 16,377リットル4ドア冷蔵庫,家電,80820,300 17,BS内蔵29型カラーテレビ,テレビ,62820,450 18,サロンヒーター,冷暖房器,8082,5000 ------------------------------------------------------

  • EXCEL VBA 他のワークシートのデータを見るには?

    EXCEL VBAでsheet1のセルに何かデータが入力された時に、sheet2のどこかのセルに同じ文字列がないかを探したいと思います。 データの入力と同時に検索をかけるため、sheet1の部分にイベントプロシージャを定義し、 データが入力された時にそのルーチンの中からsheet2のデータを見に行きたいのですが、エラーが出てしまいます。 こういうことはできないのでしょうか? Private Sub Worksheet_Change(ByVal Target As Range) Dim LineNo As Integer Dim tmp_str As String tmp_str = Target.Value LineNo = Sheets("sheet2").Cells.Find(what:=tmp_str, lookat:=xlWhole).Row MsgBox (LineNo) End Sub

  • ifjpeg.spiを呼び出すプログラムでエラー

    現在、Code Gear C++ Builder 2009 でプログラミングをしていて、ifjpeg.spiというDLLファイルの読み出しプログラムを作成しているのですが、 コマンドボタンを押して、”ProcGetPluginInfo”というデータをとりだすというプログラムなのですが、 [ILINK32 エラー] Error: 未解決の外部参照 '__fastcall TMainForm::CallButtonClick(System::TObject *)' が C:\・・(中略)・・・\VC_TEST\CPP_BUILDER_2009\TEST_PICTURE_VIEW\RELEASE\UNIT1.OBJ から参照されました このようなエラーが出てきます。 解決方法ご存じの方いらっしゃいませんでしょうか? void __fastcall TMainForm::InfoButtonClick(TObject *Sender) { char buf[80]; HINSTANCE hSPI = LoadLibrary(PluginNameEdit->Text.c_str()); //HINSTANCE hSPI = LoadLibrary("ifjpeg.spi"); //HINSTANCE hSPI; //ロードエラー if( hSPI == NULL ){ ShowMessage("プラグインファイルがロードできません"); return; } ProcGetPluginInfo GetPluginInfo = (ProcGetPluginInfo)GetProcAddress(hSPI,"GetPluginInfo"); //アドレス取得エラー if( GetPluginInfo == NULL ){ ShowMessage("Susieプラグインではありません"); FreeLibrary(hSPI); return; } //情報0 GetPluginInfo(0,buf,80); Memo1->Lines->Add(buf); //Memo->Lines->Add(buf); //情報1 GetPluginInfo(1,buf,80); Memo1->Lines->Add(buf); //情報2 for( int i=0; GetPluginInfo(i*2+2, buf, 80) > 0; i++){ Memo1->Lines->Add(buf); GetPluginInfo(i*2+3,buf,80); Memo1->Lines->Add(buf); } FreeLibrary(hSPI); } //---------------------

  • Replace関数は文字数の制限あるのでしょうか?

    アクセス2003のVBAでReplace関数で置換元のデータが大きい場合以下のエラーになります。アクセスのVBAはVB6と同じ?だと思いますが サイズの制限が存在するのでしょうか? 対策もあれば教えて欲しいです。 dim str_express as string <-- ここにアクセスのTEXT型のデータを入れている modori = Replace(str_express, str_find, str_replace) 実行時エラー'-2147352567(80020009)' 指定されたデータ量がフィールドサイズを超えています。 データ量を減らし、挿入または貼り付けを行ってください。

  • 秀丸の正規表現

    秀丸の正規表現 http://pc.dearie.jp/hidemaru/replace/14.html 上記URLでメールの正規表現について解説があります。 [A-Za-z0-9\-\.\_]+@[A-Za-z0-9\-\_]+\.[A-Za-z0-9\-\.\_]+ この正規表現でメールの検索をおこなっています。この正規表現は理解出来ます。 .*([a-z0-9\-\.\_]+@[a-z0-9\-\_]+\.[a-z0-9\-\.\_]+)([^a-z0-9@\.\-\_]+).* キャプチャを使って正規表現でメールアドレスをマッチしているのは理解できます。 なぜ置換で、「\1,」とやっても、メールアドレスのみを取得できないのでしょうか? 実際に秀丸エディタを使ってやってみましたが、メールアドレスのみ取得することができませんでした。 検索ではメールアドレスにマッチするのに、なんでキャプチャが正しく動かないのかがわかりません・・・

専門家に質問してみよう