○共有メモリを使ったアプリケーション間の通信

共有メモリを使用しますのでスピードがかなり速いです
複数のアプリケーションで文字列の同時通信ができます。
----イメージ図-----

VB6	+	shard.dll	⇔	|------------------------|
VB.net	+	shard.dll	⇔	| システム内の共有メモリ |
VBA	+	shard.dll	⇔	|                        |
VC				⇔	|------------------------|

その他、DLLの読み出せる言語ならばアプリケーション間のshardが可能です。
読み書きできる文字数は、32768バイトです。
それ以上の文字数は決して書き込まないで下さい。


@ここからAppConversation.zip (排他処理追加済み)をダウンロードしてください。
もしくは、下の方にソースがありますのでコンパイルして作成してください。
Aそのファイルを解凍するとshard.dllが出てきます。作成中のアプリケーションの実行ファイルの横にコピーしてください。
複数のshard.dllコピーして使用したとしても、システム内の共有メモリは1つしか無いので、お互いのアプリケーションが通信できます。


■ VB6でのサンプル

Private Declare Sub SetString Lib "shard.dll" (ByVal str As String)
Private Declare Function GetString Lib "shard.dll" () As String

Private Sub Command1_Click()
	Call SetString("書き込む文字列")'共有メモリに書き込み
End Sub

Private Sub Command2_Click()
	Command2.Caption = GetString()'共有メモリから読み出し
End Sub

▼ VB6のアプリケーション内部の動作を調べるために利用する時には、DLLの場所が開発環境と実行ファイル形式により変わるのでDLLを特定の場所に置いて、パスを直接指定した方が便利です。

Private Declare Sub SetString Lib "c:\shard.dll" (ByVal str As String)
Private Declare Function GetString Lib "c:\shard.dll" () As String
また、OSのバージョンにより SetString でエラーが起きる(windows10だとエラーが起きた)のでエラー処理で囲まないとプログラムが落ちます。

    On Error Resume Next
    Call SetString("Private Sub Check1_Click(Index As Integer)") '共有メモリに書き込み
    On Error GoTo 0

注意) SetString が開発環境では動作しますが、実行ファイルではプログラムが無言で落ちます←現在原因不明(Windows10で確認)
意味がわからないが、 Form_Load() の先頭で書き込む事により解決した。
Private Sub Form_Load()
    On Error Resume Next
    Call SetString("load") '共有メモリに書き込み
    On Error GoTo 0
    ....

■ VB.netでのサンプル

<System.Runtime.InteropServices.DllImport("shard.dll")> _
Private Shared Sub SetString(ByVal str As String)
End Sub

<System.Runtime.InteropServices.DllImport("shard.dll")> _
Private Shared Function GetString() As String
End Function

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
	SetString("書き込む文字列")'共有メモリに書き込み
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
	Debug.WriteLine(GetString())'共有メモリから読み出し
End Sub

■ Excel VBAでのサンプル

DLLの場所の指定がよくわからないので C ドライブ直下にコピーしてパスを直接指定しています。
SetString関数の呼び出しで書き込めるようだがエラーで常に停止するため On Error Resume Next で囲んであります。
マクロの実行でTimerStartを動かすと1秒毎にA1セルに共有メモリの内容が書き込まれ、B1セルの内容が共有メモリに書き込まれます。

Option Explicit

Private Declare Sub SetString Lib "c:\shard.dll" (ByVal str As String)
Private Declare Function GetString Lib "c:\shard.dll" () As String

Dim Timer As Date

Sub TimerStart()
    Range("A1") = GetString()
    On Error Resume Next
    SetString (CStr(Range("B1")))
    On Error GoTo 0
    Timer = DateAdd("s", 1, Now)
    Call Application.OnTime(Timer, "TimerStart")
End Sub

Sub TimerStop()
    Call Application.OnTime(Timer, "TimerStart", , False)
End Sub

■ shard.dllの中身

VC6 Win32 DLL にて作られています。
バグがあったら、連絡ください。

#include <stdio.h>
#include <windows.h>

HANDLE hFile;
char buff[32768]="";

extern "C" __declspec(dllexport) char* GetString(void){
	//アドレスを取得
	LPVOID hMap = MapViewOfFile( hFile, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0 ) ;
	
	strcpy(buff,(char*)hMap);//読み出し	
	UnmapViewOfFile(hMap);
	return buff;
}

extern "C" __declspec(dllexport) void SetString(char*str){
	//アドレスを取得
	LPVOID hMap = MapViewOfFile( hFile, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0 ) ;
	strcpy((char *)hMap,str);//書き込み
	UnmapViewOfFile(hMap);
}

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
    switch(ul_reason_for_call)
    {
		case DLL_PROCESS_ATTACH:
			hFile = CreateFileMapping( (HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, 0, 32768, "AppConversation") ;

			break;
		case DLL_PROCESS_DETACH:
			CloseHandle( hFile) ;//メモリマップドファイルをクローズ	
			break;
	}
    return TRUE;

}


▼ 排他処理の追加

実際に使用してみて、共有メモリに対して複数プロセスから読み書きすると、書き込み中に読みだしてしまったり、読み出し中に書き込んでしまったりと、
トラブルが発生すると思います。
そこで、排他処理を追加したのが次のコードです。
#include <stdio.h>
#include <windows.h>

HANDLE hFile,hMutex;
char buff[32768]="";

extern "C" __declspec(dllexport) char* GetString(void){
	HANDLE h=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"MUTEX1");//排他制御開始
	//アドレスを取得
	LPVOID hMap = MapViewOfFile( hFile, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0 ) ;
	strcpy(buff,(char*)hMap);//読み出し	
	UnmapViewOfFile(hMap);
	ReleaseMutex(h);//排他制御終了
	CloseHandle(h);
	return buff;
}

extern "C" __declspec(dllexport) void SetString(char*str){
	HANDLE h=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"MUTEX1");//排他制御開始
	//アドレスを取得
	LPVOID hMap = MapViewOfFile( hFile, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0 ) ;
	strcpy((char *)hMap,str);//書き込み
	UnmapViewOfFile(hMap);
	ReleaseMutex(h);//排他制御終了
	CloseHandle(h);
}

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
					 )
{
    switch(ul_reason_for_call)
    {
		case DLL_PROCESS_ATTACH:
			hFile = CreateFileMapping( (HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, 0, 32768, "AppConversation") ;
			hMutex = CreateMutex(NULL,FALSE,"MUTEX1");//排他制御のMUTEXを作成
			break;
		case DLL_PROCESS_DETACH:
			CloseHandle(hMutex);//排他制御のMUTEXを廃棄
			CloseHandle( hFile) ;//メモリマップドファイルをクローズ	
			break;
	}
    return TRUE;
}


■ C++言語での文字列のやり取り

難しい事を何も考えなくても VB6 ←→ VC6 での文字列のやり取りが出来るようです。
C++言語の場合にはDLLを使用しなくてもよいので、直接プログラムに書き込みます。
以下のコードがVB6とVC6での文字列のやり取りをしたプログラム
#include <stdio.h>
#include <windows.h>

HANDLE hFile,hMutex;
char buff[32768]="";

char* GetString(void){
	HANDLE h=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"MUTEX1");//排他制御開始
	//アドレスを取得
	LPVOID hMap = MapViewOfFile( hFile, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0 ) ;
	strcpy(buff,(char*)hMap);//読み出し	
	UnmapViewOfFile(hMap);
	ReleaseMutex(h);//排他制御終了
	CloseHandle(h);
	return buff;
}

void SetString(char*str){
	HANDLE h=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"MUTEX1");//排他制御開始
	//アドレスを取得
	LPVOID hMap = MapViewOfFile( hFile, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0 ) ;
	strcpy((char *)hMap,str);//書き込み
	UnmapViewOfFile(hMap);
	ReleaseMutex(h);//排他制御終了
	CloseHandle(h);
}

int main(){
	hFile = CreateFileMapping( (HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, 0, 32768, "AppConversation") ;
	hMutex = CreateMutex(NULL,FALSE,"MUTEX1");//排他制御のMUTEXを作成

	printf("%s\n",GetString());//共有メモリから読みだす
	getchar();
	SetString("あいうえおtest12345");//共有メモリに書き込む
	getchar();

	CloseHandle(hMutex);//排他制御のMUTEXを廃棄
	CloseHandle( hFile) ;//メモリマップドファイルをクローズ	
	return 0;
}


▲トップページ > Visual BASIC と C#