FMXアプリケーションとVCLアプリケーションとの間で共有メモリー

解決


yTake  2022-06-01 09:21:08  No: 150227  IP: [192.*.*.*]

yTakeです。

FMXアプリケーションとVCLアプリケーションとの間で、共有メモリーによるデータの受け渡しという事は科の言う名のでしょうか?

VCLアプリケーション間では可能という事でインターネット上でサンプルコードなども見つかります。
また、VCLとFMXの間でテザリング通信が可能という事でその例を試させて頂いた事もあります。(一応、うまく行きました)ただ、テザリングだとリモートでコマンドを実行するというイメージで、データの受け渡しが可能かまだ調べ切れていません。

主として、FMX環境で開発していますが、どうしてもVCL環境でしか使えないライブラリがあり、取得されたデータ(構造体として保持)をFMXアプリケーションへ渡したいと考えています。

まず、VCLアプリケーションとFMXアプリケーションとの間で構造体などのデータをやり取りする事は可能でしょうか?(共有メモリーでなくても実現できればOKです)


WIndows10+DELPHI XE6
です。

編集    削除
take  2022-06-01 15:57:05  No: 150228  IP: [192.*.*.*]

VCLとFMX間ではわかりませんが
32bitアプリと64bitアプリや権限が異なるアプリ間で少量のデータのやりとりなら
自分の場合はウインドウズメッセージによるプロセス間通信にするかな?

自分自身のIPアドレス宛にTCP/IP通信をするという手もありますが
今のWindowsだと警告が出てしまうかもしれません。

編集    削除
yTake  2022-06-01 22:11:36  No: 150232  IP: [192.*.*.*]

Takeさん、
コメントをありがとうございます。
プロセス間通信、ウィンドウズ・メッセージですか?調べてみます。
ご助言の中で気になったのは、”少量のデータ”のやり取りというところです。
こちらで想定しているデータは比較的大きなものになります。数MB~十数MB程度です。
これでは少量のやり取りには該当しない様に思えます。
とすると、可能性が高いのは自分自身宛てにTCP/IP通信という事でしょうか?
警告は出るけれど、実現は可能という事でしょうか?


編集    削除
take  2022-06-02 07:55:48  No: 150234  IP: [192.*.*.*]

ウインドウメッセージではせいぜい4kbyteぐらいのデータを一度に送るぐらいです。
TCP/IPでもパケットが分割されると面倒なのでそれぐらいかな

数MB~十数MBの情報ならファイルにするかデータベースにするかな

どちらも共有メモリのようにはいきませんね。

編集    削除
yTake  2022-06-02 10:54:24  No: 150235  IP: [192.*.*.*]

そうですか。
いずれも数kB程度なのですね。

共有メモリという選択肢が無い様な記述に感じますが、VCLとFMXの間で共有メモリを介してデータを受け渡しする事は出来ないという事でしょうか?

ファイルにするのであれば、現状と同じという事になってしまいます。
現状:
1)VCLアプリケーションでデータを取得しファイルの保存し終了。
2)FMXアプリケーションを起動しファイルに保存したデータを読み込み作業。
となっていて、これを、
1)FMXアプリケーションからVCLアプリケーションを呼び出し、共有メモリ等を使用して、VCLからデータを受け取り作業を続ける様にしたい。(VCLアプリケーションは終了させてもOK)

この様な事は実現できないでしょうか?

編集    削除
take  2022-06-02 11:13:40  No: 150236  IP: [192.*.*.*]

DEKO様の資料にVCLとFMXを混在させる方法が掲載されていますけど
試して見てはいかがでしょうか?

https://ht-deko.com/ft1507.html

編集    削除
久美子  2022-06-02 12:09:47  No: 150237  IP: [192.*.*.*]

具体的な内容がわかりませんので、外しているかもしれません。
VCLアプリケーションを実行するからには、Windows上で実行するアプリを作成されていると想像します。
そうであれば、
「取得されたデータ(構造体として保持)をFMXアプリケーションへ渡したい」ということであれば、
DBをVCLアプリケーションで更新  ⇒  FMXアプリケーションで更新されたデータを読み込み、
と、両方のプログラムから共用するデータベースを介してのやり取りではダメなんでしょうか?

編集    削除
HFUKUSHI  2022-06-02 12:29:11  No: 150238  IP: [192.*.*.*]

プラットフォームがWindows限定ならメモリマップドファイルでしょうかね。このへん見て作ったことがあります。
メモリマップドファイルを使ったデータの共有
http://rakasaka.fc2web.com/delphi/mapping.html

純粋にWindows(Win32API)にのみ依存しているので、VCL/FMXを跨いでも大丈夫でしょう。
(書き込みはMutexで保護、変更の通知はPostMessageでメッセージをブロードキャスト、とかも追加で用意しました)

もしプラットフォームを跨ぐのであれば、TCP/UDPでの通信や、RDBを使う、という選択肢が考えられます。

編集    削除
yTake  2022-06-02 15:13:39  No: 150239  IP: [192.*.*.*]

Takeさん、
情報をありがとうございます。
参照させて頂きます。

使い勝手の上で、VCL機能とFMX機能とを頻繁に使い分ける分けではありません。
両環境を共存させて行き来する様な事はないと思います。
将来的にはこの様な運用が視野に入ってくるかもしれません。

貴重な情報をありがとうございます。

編集    削除
yTake  2022-06-02 15:22:38  No: 150240  IP: [192.*.*.*]

久美子さん、
ありがとうございます。
はい。現時点ではWindows上のみでの生成です。

実はDBは組みこむ予定ではあります。VCLから取得したデータを解析して、その結果を時系列で管理する為です。
(Embeded FireBirdを想定しています)
DBは解析結果のみを保存する仕様ですが、ここに元データも登録出来る様にして、VCLからFMXへのデータのやり取りにも利用するという事を意味しているのでしょうか?
DBが巨大化してしまいますが、容量的には余裕はあるので、可能性はある様に思います。

DBを介してのやり取りの意味が良く分かっていません。

この様な解釈であっていますでしょうか?

編集    削除
yTake  2022-06-02 15:28:37  No: 150241  IP: [192.*.*.*]

HFUKUSHIさん、
ありがとうございます。
今のところ、プラットフォームはWindowsのみです。
メモリーマップドファイルですね。
想定している手法に近いやり方の様に思います。
参考にしてみたいと思います。
当面プラットホームを跨ぐ予定はありません。

先ずは、メモリーマップドファイルを試してみたいと思います。

編集    削除
久美子  2022-06-02 16:40:56  No: 150242  IP: [192.*.*.*]

私の提案は、
FMX側で、発生した原始データをDBの受け渡し用テーブルに追加で書き込む
VLC側に、パメタ受け渡し用テーブルのレコードID等を渡して、VLCアプリを起動。
VLC側で、原始データを読んで加工処理し、成果をテーブルに書き込む
FMX側で、成果テーブルを読み込んで処理。
必要なければ、DBから原始データと加工の成果のレコードを削除
イメージとしてはシンプルに設計できるような気がします。

運用が、スタンドアローなのかネットワーク上で複数人での使用なのか等で必要な処理は変わってくるかと思いますが、
メモリーマップドファイルは触ったことがないですが、方法は何通りかある思います。
あとは、ご人身の感覚とこれまでの資産等で判断されるのがよろしいかと思います。

質問から離れてしまいますし、おせっかいを承知で申し上げるなら、
Windows上で動かすのであれば、お勧めするのは、すべてをVCLで作成すれば、二つのプログラムのやりとりのオーバーヘッドも生じなくて一番シンプルなような気がします。



編集    削除
久美子  2022-06-02 16:43:05  No: 150243  IP: [192.*.*.*]

すみません。VLC⇒VCL  です。

編集    削除
AAA  2022-06-02 19:43:15  No: 150244  IP: [192.*.*.*]

VCL側を DLL か ActiveX にしてしまえば?

編集    削除
mam  2022-06-03 09:26:54  No: 150245  IP: [192.*.*.*]

ファイルの受け渡しが嫌な理由がわからないのですが、
1)VCLアプリケーションでデータを取得しファイルを時刻+乱数のファイル名で保存し、FMXアプリを引数「ファイル名」で起動させ、自身を終了させる。。
2)FMXアプリケーションが起動したらファイルに保存したデータを読み込み、元ファイルを消して作業する。
では駄目なのでしょうか?

編集    削除
yTake  2022-06-03 11:54:07  No: 150248  IP: [192.*.*.*]

久美子さん、
そうですね、何も全てデータベースに記録として保存する事はなく、構造体データは、VCL<->FMXの受け渡しにのみ用いて、必要無くなれば、削除しても良いですね。
DB方式も良さそうです。


AAAさん、
ありがとうございます。
DLL化ですか、思いもよりませんでした。
すみません。イメージが湧きません。
DLL化したVCLアプリは、やはり別アプリの様な振る舞いになって結局データの受け渡しに困りそうです。
DLL化した事により、関数の戻り値か外部変数の形で参照が可能になるという事でしょうか?
知識不足ですみません。


mamさん、
ありがとうございます。
ごもっともです。
ファイルによる受け渡しは現在がそうなっています。
VCLでの保存操作とFMXでの読み込み操作が煩雑で、いわゆるシームレスな運用の為、ファイル保存をやめてデータでの受け渡しを考えています。
ただ、ご指摘の様にVCL側でファイル名を自動生成にして保存し、そのファイル名をFMX側へ渡して、FMXでそのデータを暗黙的に読み込めば共有メモリーと事実上同じ事になりますね。
問題は、ファイル名の受け渡し方法になります。
FMXアプリがメインになって、子プロセスとしてVCLを起動し、保存したデータファイル名をFMXへ渡して終了し、FMXで処理を続ける様になります。


根本的には、終始VCLで行えば全て丸く収まります。先行してFMXで実現している部分がある為、VCLー>FMXのデータ移行を探っています。また、FMXで進めていましたのでプラットフォームフリーも目指したいところです。
プラットフォームフリー化の懸念は、現在、VCLでのデータ取得の部分でもあります。


現在は実現できているところから、徐々にFMX化プラットフォームフリー化出来たら良いと思います。

編集    削除
AAA  2022-06-03 18:27:28  No: 150249  IP: [192.*.*.*]

アプリじゃなくて 
どうしてもVCL環境でしか使えないライブラリがあり

DLLにするんだよ?

編集    削除
mam  2022-06-06 17:00:41  No: 150250  IP: [192.*.*.*]

重いですけど、DDEだと以下で通信できました。

//DDEで送信する クライアント側(VCL)Project1
uses Vcl.DdeMan;
procedure TForm1.Button1Click(Sender: TObject);
var DdeC:TDdeClientConv;
begin
  DdeC:=TDdeClientConv.Create(self);
  //アプリケーション名(DDEサーバー側の.exe無し),TDDEServeerConv.name
  if DdeClientConv1.SetLink('Project2', 'dde') then
  begin
    DdeClientConv1.ExecuteMacro(
      PAnsiChar(
        AnsiString(
          dupeString('12345678901234567890'#13#10,1024*1024)
        )
      ),true);
  end;
  DdeC.Free;
end;

//DDEで受信するサーバー側(FMX)Project2
unit Unit1;
interface
uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs
  ,Vcl.DdeMan, FMX.Controls.Presentation, FMX.StdCtrls, FMX.ScrollBox, FMX.Memo;
type
  TForm1 = class(TForm)
    Memo1: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { private 宣言 }
    dde:Vcl.DdeMan.TDdeServerConv;
    procedure ExecuteMacro(Sender: TObject; Msg: TStrings);
  public
    { public 宣言 }
  end;

var
  Form1: TForm1;

implementation
{$R *.fmx}
procedure TForm1.FormCreate(Sender: TObject);
begin
  dde:=Vcl.DdeMan.TDdeServerConv.Create(Form1);
  dde.Name:='dde';
  dde.OnExecuteMacro:=ExecuteMacro;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  dde.Free;
end;

procedure TForm1.ExecuteMacro(Sender: TObject;
  Msg: TStrings);
begin
  Memo1.Lines.Text:=Msg.Text;
end;

end.

編集    削除
yTake  2022-06-06 19:37:52  No: 150252  IP: [192.*.*.*]

AAAさん
VCLのライブラリをDLLにするという意味だったんですね。

説明不足ですみませんFMXでVCLライブラリ(実はDLL)の機能を実現できれば、最も望ましい形ではあります。

実際、一部機能はFMXで実現できていますが、肝心な機能が実現できていません。
肝心な機能とは、48ビットカラーデータをTWAIN制御のスキャナーから取得する事です。

TWAIN自体はVCL、FMX共に動作しています。
現在、VCLではDLLを使用して、48ビットカラーデータをTWAINスキャナーから取得できています。
しかし、FMXではインタ―ネットで公開されていたTWAINとのI/Fのコードを使用して、24ビットカラーのデータの取得までは出来ていますが、48ビットカラーに関して取得出来ていません。
DIBや転送モード(48ビットカラーの場合メモリー転送モードである必要がある)が関係してくるのですが、修正すべき点が分かっていません。

そこで、VCLで取得した48ビットカラーデータを共有メモリーでFMXへコピーする事を考えた次第です。

編集    削除
yTake  2022-06-06 19:58:14  No: 150253  IP: [192.*.*.*]

mamさん、
ありがとうございます。
DDEですか。
共有メモリーではなくS/C通信という事ですね。
共有メモリーではMemoryMappedFileを試しています。サンプルは正常に実行できましたが、本来の構造体データで試そうとすると、”CopyMemory”のところでAccess Violationとなります。

構造体を
type
    RMMF_MTX  = Record
         MTX  : Array [ 1 .. 3 ] of Array of Array of Word;
    End;
と定義し、
var
   mmf_mtx  :  RMMF_MTX;
と定義し、
   P := MapViewOfFile( HFILE_2, FILE_MAP_WRITE, 0, 0, 0 );  で、マッピングしています。
VCLで取得したマトリックスのサイズ(x,y)から、
mmf_mtxのサイズを、
siz := SIzeOf( Word ) * x * y * 3 ;
で計算し、
CopyMemory( P, @mmf_mtx, siz );
で、共有メモリーへコピーしていると思うのですが、、、


DDEも試してみたいと思います。

編集    削除
yTake  2022-06-08 09:42:25  No: 150257  IP: [192.*.*.*]

解決しました。

メモリーマップドファイルの作成時点でのサイズ指定に誤りがありました。

   siz     := SIzeOf( Word ) * x * y * 3 ; 
   HFILE := CreateFileMapping( $FFFFFFFF, nil, PAGE_READWRITE,
                      0, size, '_FileMappingData' );

として、うまく行きました。

ただ、このVCLー>FMX転送されるべきデータのサイズは取得してみないと分からない為、MemoryMappedFile(=MMF)を二つ用意し、一方のMMFにデータサイズのみを共有し、もう一方のMMFをそのデータサイズで作成し、転送に使用するという形になりました。


この他、データベースを介する手法DDE手法など、順次試せればと思います。

皆様、ありがとうございました。

編集    削除
HFUKUSHI  2022-06-08 10:57:00  No: 150259  IP: [192.*.*.*]

CreateFileMappingの第1引数は$FFFFFFFFではなくINVALID_HANDLE_VALUEにしておいたほうがよさそうです(x64を考慮)

編集    削除
yTake  2022-06-09 09:01:18  No: 150260  IP: [192.*.*.*]

HFUKUSHIさん
ありがとうございます
FMX側は64bitアプリケーションなので、その様にしてみます。

編集    削除