헷갈리기 쉽지만, 

하기처럼 하면 됨.

 

 

float fDat = 112.445;


std::vector<void*> aDat;
aDat.push_back((void*)&fDat);

LPVOID lpVoid = aDat.at(0);
float aDat1 = *(float*)lpVoid;

float fDat2 = *(float*)aDat.at(0);

 

 

int 형태

ULONG anCount = (ULONG)aDat.at(0);

 

항상 헷갈리는 이슈.

 

유니코드 환경에서 WCHAR을 사용하곤하지만,

CString의 편리함을 잊을수 없기에.. 

 

하기처럼 define해 놓고 쓰면 편하다.

 

CString -> string

#define CSTR2STR(s) ((string)CT2CA(s.operator LPCWSTR()))

 

string -> CString   %S 대문자로 기록하면 변환가능

CString szBuf;

string sz;

szBuf.Format("%S", sz.c_str());

 

[MSDN에서 발췌]

// 가변인자로 받아 처리하기

Requirements

Header Use for

cstringt.h MFC-only string objects
atlstr.h Non-MFC string objects

void WriteString(LPCTSTR pstrFormat, ...)
{
CString str;

// format and write the data you were given
va_list args;
va_start(args, pstrFormat);

str.FormatV(pstrFormat, args);
va_end(args);

_tprintf_s(str);
return;
}

비쥬얼 스튜디오 - 단위 테스트(유닛 테스트)

 

MS 참고.

https://docs.microsoft.com/ko-kr/visualstudio/test/getting-started-with-unit-testing?view=vs-2019&viewFallbackFrom=vs-2015

 

유닛 테스트 시작 - Visual Studio

유닛 테스트 시작Get started with unit testing 이 문서의 내용 --> Visual Studio를 사용하여 단위 테스트를 정의하고 실행하여 코드 상태를 유지 관리하고, 코드 적용 범위를 확인하고 , 고객이 찾기 전에 오류와 결함을 찾을 수 있습니다.Use Visual Studio to define and run unit tests to maintain code health, ensure code coverage, and find er

docs.microsoft.com

하기 블로그 참고.

https://m.blog.naver.com/sogangori/220608227176

 

비쥬얼 스튜디오 - 단위 테스트(유닛 테스트)

비쥬얼 스튜디오에 C++과 C#의 유닛 테스트 프로젝트가 내장되어 있습니다. 즉시 사용할 수 있기 때문에 ...

blog.naver.com

 

 

 

하기처럼 하는데 속도가 개선됨.

 

float **arr;
arr = (float **)malloc(sizeof(float *) * nX);
arr[0] = (float *)malloc(sizeof(float) * nX*nY);
for (int i = 1; i < nX; i++){
arr[i] = arr[i - 1] + nY;
}

arr[0][1000] = 500.4f;
arr[1000][1000] = 1000.4f;
arr[1999][1000] = 2000.4f;


float **arr1;
arr1 = (float **)malloc(sizeof(float *) * nX);
arr1[0] = (float *)malloc(sizeof(float) * nX*nY);
for (int i = 1; i < nX; i++){
arr1[i] = arr1[i - 1] + nY;
}


DebugString(L"parallel_for copy .. start");
concurrency::parallel_for(0, nX, [&](int X)
{
memcpy(arr1[X], arr[X], (sizeof(float) * nY));
});
DebugString(L"parallel_for copy .. stop");

float data(4Byte) 4096 x 3072 데이터 복사 시간.

메모리 복사시에는 Assert가 발생됨.

 

for 구동시 약 14~15ms 소요 (일정)

Parallel_for 구동시 편차가 발생 max: 15ms,   min 6ms (편차발생)

 

 

전체 소스
#include <iostream>

#include <ppl.h>

 

void CMFCApplication1Dlg::OnBnClickedOk5()
{
int i = 0;
int nX = 4096, nY = 3072;
float** fData = NULL;

fData = (float**)malloc(sizeof(float*) * nX);
for (i = 0; i < nX; i++)
{
fData[i] = (float*)malloc(sizeof(float) * nY);
memset(fData[i], 0x0, sizeof(float) * nY);
}

fData[0][1000] = 500.4f;
fData[1000][1000] = 1000.4f;
fData[1999][1000] = 2000.4f;

SetScanData(fData, nX, nY);
}

 

void CMFCApplication1Dlg::SetScanData(float** afData, int anX, int anY)
{
std::string sz = typeid(afData).name();

int i = 0;
if (afData == NULL)
{
assert(0);
return;
}

m_fData = (float**)malloc(sizeof(float*) * anX);
for (i = 0; i < anX; i++)
{
m_fData[i] = (float*)malloc(sizeof(float) * anY);
memset(m_fData[i], 0x0, sizeof(float) * anY);
}

#if 1

DebugString(L"parallel_for copy .. start");
concurrency::parallel_for(0, anX, [&](int nX)
{
for (int nY = 0; nY < anY; nY++)
{
m_fData[nX][nY] = afData[nX][nY];
}
});
DebugString(L"parallel_for copy .. stop");

 

DebugString(L"for loop copy .. start");
for (int nX = 0; nX < anX; nX++)
{
for (int nY = 0; nY < anY; nY++)
{
m_fData[nX][nY] = afData[nX][nY];
}
}
DebugString(L"for loop copy .. end");

#else

memcpy(m_fData, afData, (sizeof(float) * anX) * anY);

#endif

for (i = 0; i < anX; i++)
{
free(m_fData[i]);
}

free(m_fData);
}

현재 시간을 출력하면서 로그로 확인하기

가변인자를 활용

 

void TestProc::DebugString(LPCTSTR alpszData, ...)

{

CString strRcv;

va_list argptr;

va_start(argptr, alpszData);

strRcv.FormatV(alpszData, argptr);

va_end(argptr);

 

CString str;

SYSTEMTIME sysTime;

::GetLocalTime(&sysTime);

str.Format(L"%02d:%02d:%02d.%03d %ws\n", sysTime.wHour, sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds, strRcv);

OutputDebugString(str);

}

wsprintf는 부동소수점 수를 출력하는 포맷이 없습니다.

 

%f, %lf 지원 안합니다.

 

 

부동소수점수를 출력하고 싶으면, 직접 함수를 만들면됩니다.

 

만들기 싫으면 c의 함수인 sprintf 를 사용하면 됩니다.

 

혹시 유니코드를 사용한다면 swprintf 를 사용하면 됩니다.

 

멀티바이트나 유니코드 신경 안쓰고 사용할려면 _stprintf 를 사용하면 됩니다.

 

 

sprintf 함수는 stdio.h 에 선언 되어 있으니 , 이 헤더 파일을 포함 시켜 주면 됩니다.

 

 

https://msdn.microsoft.com/ko-kr/library/h90dkhs0(v=vs.90).aspx

 

 

=============================================

출처- 하기 블로그에서 참고하였으며, 문제가 되면 삭제하겠습니다.

        http://legendfinger.tistory.com/449

=============================================

 

 

공유 메모리 

일반적으로 exe나 DLL안의 전역변수들은 기본적으로 PAGE_WRITECOPY 속성이 지정되기 때문에 쓰기전에 복사본이 만들어진다(Copy-On-Write) 그러므로 A와 B는 둘 다 다른 물리 공간을 사용하게 된다.

하지만 DLL내에 공유 메모리를 만들어 사용하면 서로 다른 2개의 프로세스가 DLL내의 공유 메모리를 사용해서 통신할 수 있다.

 

DLL 공유 섹션 만드는 방법

#pragma data_seg("SHARED")

char shared_buffer[1024] = {0};

#pragma data_seg()

 

#pragma comment(linker, "/subsystem:SHARED,RWS")

 

단점(보안에 취약하다)

DLL은 Kernel Object의 보안속성을 줄수 없으므로 다른 프로세스에서 DLL을 로드하여 데이터를 가로챌수있다.(보안에 상관없는 통신에서 사용해야한다)

 

 

--------------------------------- X.dll -------------------------------------

공유 메모리 설정 DLL 파일

구성 파일 : X.h, a.cpp

 

X.h 

// X.h

 

#include <windows.h>

 

#ifdef DLLSOURCE

        #define DLLAPI __declspec(dllexport)

#else

        #define DLLAPI __declspec(dllimport)

#endif

 

EXTERN_C DLLAPI void Set(int);

EXTERN_C DLLAPI int        Get();

 

//--------------------------------------------------

 

 

a.cpp

 

// a.cpp

 

#define DLLSOURCE

 

#include "X.h"

 

// DLL 안에 공유 메모리를 만들면 이 DLL을 사용하는 모든 프로세스에서

// 공유 할 수 있다.

#pragma data_seg("SHARE")

int x = 0;        // 주의! 반드시 초기화된 data만 공유 메모리에

                  // 들어갈수있다.

#pragma data_seg()

 

 

#pragma comment(linker, "/section:SHARE,RWS")

// " "안에 띄여쓰기 하지 마라

 

void Set(int value)

{

        x = value;  // 공유 메모리를 변경한다

}

 

int Get()

{

        return x;

}

 

 

----------------------- AA.exe ------------------------------

공유메모리에 값을 할당하는 프로그램

 

#include <windows.h>

#include <stdio.h>

 

// X.h와 X.lib 복사해 와라

#include "X.h"

#pragma comment(lib, "X.lib")

 

void main()

{

        HANDLE hEvent = CreateEvent(0, 0, 0, "e");

 

        while(1)

        {

                int n = 0;

                printf("숫자를 넣으세요 >>");

                scanf("%d", &n);

 

                Set(n);       // DLL 안에 있는 공유 메모리에 data를 넣는다

 

                SetEvent(hEvent);

        }

}

 

// X.h와 X.lib는 현재 폴더에 복사해오세요

// X.dll은 c:\\winnt 아래에 복사해두세요

//      - BB프로세스와 공유하기 위해

 

 

 

------------------------------ BB.exe ---------------------------------

공유 메모리 값을 출력하는 프로그램

 

#include <windows.h>

#include <stdio.h>

 

// X.h와 X.lib 복사해 와라

#include "X.h"

#pragma comment(lib, "X.lib")

 

// DLL 안에 공유 메모리를 사용한 IPC 기법

 

void main()

{

        HANDLE hEvent = CreateEvent(0, 0, 0, "e");

 

        while(1)

        {

                WaitForSingleObject(hEvent, INFINITE);

 

                int n = Get();

 

                printf("X 값 : %d\n", n);

        }

}

 

// X.h와 X.lib는 현재 폴더에 복사해오세요

 

// B를 먼저 실행하고

// A를 실행 해보세요

// A에 값을 넣고 Enter

 

 

 

=============================================

출처- 하기 블로그에서 참고하였으며, 문제가 되면 삭제하겠습니다.

        http://blog.daum.net/mrdk/60

=============================================

 

callback 함수를 알아보기 전에..

   먼저 함수를 가리키는 포인터를 만들어서 그 포인터로 어떤 함수를 호출하는 방법에 대해 알아보자.

 

  먼저 다음과 같이 type def를 한다.

  typedef int (*func) (int);

 

  이렇게 하면,  func는  int를  return하고 int를 인자로 받아들이는 함수를 가리키는 포인터의 형이 된다.

  이와 같은 형태의 함수면 어떤 거든 포인트 할 수가 있다.

 

   예를 들어

   int example_function(int param1)

   {

          printf("%d",param1);

    }

    다음과 같은 함수가 있다면,

   

   func pointer_to_func;

   pointer_to_func = example_function; 

   pointer_to_func(5); 

   이것은 곧...

   example_function(5); 와 동일한 결과를 낳는다.

 

   여기까지가...

   함수에 대한 포인터를 만들어서 이 포인터로 함수를 호출하는 방법에 해당한다....

 

   그러면 DLL에서를 생각해보자. DLL이 쓰이는 상황은,

    User Program 과 DLL로 나눠서 생각을 해봐야 한다.

   

    DLL에 함수들이 잔뜩 있으며, User Program에 함수가 잔뜩 있다.

    우리는 DLL에서 User Program의 함수를 호출하게끔 만들고 싶을 수 있다.

    특정 파라메터를 가지고 DLL에서 user Pgoram의 함수를 호출하게 하여

    통신 비스므리한 효과를 내는 것이다.

 

    

  이를 위해서는 그림에서 보다시피,

  User Program에서는 그렇게 호출받기 원하는 함수를 정의한다. 함수1이 정의 되었으면,

  DLL에 있는 레지스터콜백을 위한 함수에다 이 함수의 이름(포인터)를 넘겨주면

  콜백이 등록이 되는 것이다.

  

   그러면, DLL에서는, 이렇게 넘겨온 함수에 대한 포인터를 가리킬 전역변수를 하나 만들고(func callbackFunc

   DLL레지스터콜백에서는 넘겨온 함수의 포인터를 callbackFunc에 배정을 시킨다.

 

   그러면 어떤다른 함수에서 user Program의 특정 함수를 호출해야 겠다 싶으면,

    callbackFunc()를 호출하면 user Program에서 지정한 함수가 호출되게 되는 것이다.


void CxxxDlg::OutputDispData(CONST TCHAR* pBuf, ...)
{
 va_list     ap; 
 TCHAR szInformBuf[1024]{0}; 
   
 if (pBuf != NULL)
 {
  va_start(ap, pBuf);
  ::_vsntprintf_s(szInformBuf, sizeof(szInformBuf) / sizeof(TCHAR), sizeof(szInformBuf),pBuf, ap);
  va_end(ap);  


 } 

}

 

 

// char * 가변인수

 if(pBuf != NULL)
 {
  va_start( ap, pBuf );
  vsprintf( szInformBuf , pBuf, ap );
  va_end( ap );
}

 

+ Recent posts