제작한 검사프로그램과 설비 프로그램의 버젼차이가 커서 도저히 양립할 수 없어
-visual studio 2010(vc++11 안됨) 32bit 시스템 <-> 2017에서 제작 64bit opencv 4.10버젼(64bit만 제공)
cmake로 32bit로 만들어 써도 결국 vc++11 은 필요한 상황
설비사와 타협을 본게 : 검사프로그램 ↔ 공용 메모리 ↔ 설비프로그램
이렇게 서로 공용구간에다 이미지를 넘기고 검사를 하고 검사결과에 번호를 입혀 다시 공용구간에 넘기면 설비프로그램이 가져가 표시하는 것으로 합의를 봤습니다.
예제가 필요해 최호승님이 쓴 열혈 mfc2008(프리랙)을 봤는데 MMF라는 예제가 있었습니다.
간단한 문자열을 전달하는 예제를 제공하십니다.
IPC라고 인터넷에 찾으면 리눅스에서 쓰는 시스템들이 많이 나옵니다.
MFC(c++)로 쓰실분들은 반드시 MMF예제를 찾아쓰세요
저는 구조체를 따로 만들지 않고 포인터로 가르켜 1~4번은 테스트 결과번호와 테스트 완료 여부등의
공간으로 활용하고 5번부터 이후는 모두 이미지를 BYTE로 만들어 넘겼습니다.
그리고 받아쓰는 쪽에서는 Mat함수로 opencv형태로 변경해서 쓰고 다시
BYTE형태로 반납했어요
본인이 쓰시는 형태에 맞게 쓰시면 될텐데 사실 dll로 간단하게 제공해 쓸려고 하던게
버젼문제로 이렇게 되었지
많이 쓰지는 않을 것 같습니다. 이종 프로그램이나 설비간 연결 시
유용할 것 같긴하네요
프로그램 처음부터 끝까지 다 관장하시는 경우
굳이 필요는 없어보입니다.
큰 흐름은 아래와 같습니다.
- 파일 오픈 hF=CreateFile("sharedmemory.txt")
=> 이름은 양쪽에서 같게 맞춰줍니다.
- 파일 내용을 메모리에 올린다 hMapF=CreateFileMapping(hF)
- 메모리에 올려진 첫번째 주소를 얻는다. pF=MapViewOfFile(hMapF)
=> 결국 이 핸들로 조정합니다.
- 첫번째 주소로 메모리 내용을 조작한다.
- 중간중간에 변경된 내용을 강제로 디스크에 쓰게만든다. FlushViewOfFile(pF)
- 해제. UnmapViewOfFile(pF);
- 해제. CloseHandle(hMapF);
- 파일 닫기. CloseHandle(hF);
복잡해보이는데 결국 pF 로 데이터 조작이 이루어지게 됩니다.
(최호승님 책예제도 좋습니다. 책의 예제 소스는 프리랙 홈페이지에도 제공)
<예제>
#include <windows.h>
#include <stdio.h>
//필요에 따라 추가 include
int main(int argc, char *argv[])
{
HANDLE hF, hMapF;
DWORD fSize, i;
char *pF, *pFtmp;
hF=CreateFile("test.txt",GENERIC_READ|GENERIC_WRITE, 0,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
fSize=GetFileSize(hF,NULL);
hMapF=CreateFileMapping(
hF, //file handle
NULL,
PAGE_READWRITE,
0, //file size
0, //file size
NULL); //map name
if(hMapF==NULL)
{
printf("CreateFileMapping() fail");
CloseHandle(hF);
return 1;
}
pF=MapViewOfFile(hMapF,FILE_MAP_ALL_ACCESS,0,0,0);
pFtmp=pF;
for(i=0;i<fSize;i++)
{
*pFtmp=(*pFtmp+1);
pFtmp++;
}
//메모리 내용을 강제로 파일에 쓴다.
FlushViewOfFile(pF, 0);
UnmapViewOfFile(pF);
CloseHandle(hMapF);
CloseHandle(hF);
return 0;
}
Share Memory를 만드는 프로세스:
CreateFileMapping->MapViewOfFile->UnmapViewOfFile->CloseHandle
Share Memory를 Open하는 프로세스:
OpenFileMapping->MapViewOfFile->UnmapViewOfFile->CloseHandle
<예제>
<공유메모리를 만들고 공유메모리에 데이터를 써넣는 프로그램>
#include <windows.h>
#include <stdio.h>
#pragma pack(1)
typedef struct tag_SMTEST
{
char c;
int i;
short s;
} SMTEST;
int main(int argc, char *argv[])
{
HANDLE hMapF;
SMTEST *psm;
// JJBSMTEST라는 이름으로 공유메모리를 만든다.
hMapF=CreateFileMapping(
INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
0,
sizeof(SMTEST),
"JJBSMTEST");
if(hMapF==NULL)
{
printf("CreateFileMapping() fail");
return 1;
}
psm=(SMTEST *)MapViewOfFile(hMapF,FILE_MAP_ALL_ACCESS,0,0,sizeof(SMTEST));
//이후부터 psm 포인터만 읽으면 파일의 내용을 자유롭게 액세스할 수 있다.
// 파일이 프로세스의 주소 공간에 맵되어 있으므로 포인터를사용하면 연결된 파일의 원하는 부분을 읽을 수 있다.
psm->c='a';
psm->i=100;
psm->s=10;
//아래 프로그램을 실행할수있게 시간을 주자
Sleep(10000);
UnmapViewOfFile(psm);
CloseHandle(hMapF);
return 0;
}
<예제>
<공유메모리에 접근하여 데이터를 출력하는 프로그램.>
#include <windows.h>
#include <stdio.h>
#pragma pack(1)
typedef struct tag_SMTEST
{
char c;
int i;
short s;
} SMTEST;
int main(int argc, char *argv[])
{
HANDLE hMapF;
SMTEST *psm;
// JJBSMTEST라는 이름으로 공유메모리에 접근한다.
hMapF=OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, "JJBSMTEST");
if(hMapF==NULL)
{
printf("OpenFileMapping() fail");
return 1;
}
psm=(SMTEST *)MapViewOfFile(hMapF,FILE_MAP_ALL_ACCESS,0,0,sizeof(SMTEST));
//공유메모리에 설정된 내용을 출력한다.
printf("c:%c i:%d, s:%d\n",psm->c,psm->i,psm->s);
UnmapViewOfFile(psm);
CloseHandle(hMapF);
return 0;
}
<예제> 파일을 메모리에 올려놓고 마음대로 불러다 쓴다.
typedef struct Member
{
char Id[256];
char name[256];
}Member;
Member * member;
Member mem[1000];
void Init()
{
int i=0;
for(i=0; i<1000; i++)
{
strcpy(mem[i].Id, "22");
strcpy(mem[i].name, "22");
}
}
void FileSet()
{
DWORD dwWritten;
hFile = CreateFile("c:\\jinyong.dat", GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile!=INVALID_HANDLE_VALUE)
{
WriteFile(hFile, mem, sizeof(Member)*1000, &dwWritten, 0);
}
CloseHandle(hFile);
}
void Mapping()
{
HANDLE hFile2;
int i=0;
hFile2 = CreateFile("c:\\jinyong.dat", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
if(hFile2 != INVALID_HANDLE_VALUE)
{
hMap = CreateFileMapping(hFile2, NULL, PAGE_READWRITE, 0, 0, NULL);
member = (Member *)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
}
printf("%s\n",member[2].Id);
printf("%s\n",member[3].name);
}
참조 블로그 : https://yonghello.tistory.com/m/entry/%ED%8C%8C%EC%9D%BC%EB%A7%A4%ED%95%91%EC%98%88%EC%A0%9C
이 기본 예제를 가지고 저는 새로 만들었는데
일단 사진이 넘어가는 것까지는 만들었습니다.
회사에서 만든 것이라 올릴 수 가 없어
완성되면 다시 업로드해보겠습니다.
저 같은 경우에있는 설비 엔지니어분들에게
작으나마 도움이 되셨길.....
'프로그래밍학습 > MFC' 카테고리의 다른 글
MFC int to string 변환 방법 (0) | 2021.05.14 |
---|---|
error C2143: 구문 오류 : ';'이(가) '*' 앞에 없습니다. (0) | 2021.05.11 |
c2440: 'static_cast':'void(_thiscall CDlgtest::*)(WPARAM,LPARAM)'에서 LRESULT(_thiscall CWnd::*)변환할수 없습니다. (0) | 2021.04.16 |
[MFC]배열을 포인터로 전달하기- c++ (0) | 2021.03.20 |
[MFC]컨트롤 클릭 이벤트 (0) | 2021.03.11 |
댓글