728x90
반응형
C#에는 기본적으로 포인터를 지원하지 않는다. 포인터를 사용하기 위해서 unsafe를 이용하던데, 기본적으로 사용하지 말라고 한 것을 굳이 사용해야 싶어서 구글링 해서 여기저기 검색해 보았다. 가장 간단한 방법으로 C++에서도 사용하던 것인데 포인터의 주소를 넘기는 것이다. 포인터의 주소는 32bit에서는 long으로 64bit에서는 __int64 혹은 long long으로 넘겨주곤 했다. C#은 모두 long long이다. 그렇기 때문에 OCX의 메서드를 만들 때에도 LONGLONG으로 만들어야 한다.
void CtopgraphCtrl::AddArrayDataPtr(LPCTSTR name, LONG length, LONGLONG xPtr, LONGLONG yPtr, LONGLONG zPtr)
포인터의 길이를 나타내는 length와 각 데이터의 주소를 담을 LONGLONG 변수를 선언했다. 이는 단순하게 포인터로 변경할 수 있다.
double *x = (double *)xPtr;
double *y = (double *)yPtr;
double *z = (double *)zPtr;
double 포인터를 넘길 예정임으로 이런 식으로 변경할 수 있다.
C#에서는 long이 LONGLONG이기 때문에 아래와 같이 선언한다.
void AddArrayData([MarshalAs(UnmanagedType.LPWStr)] string name, int length, long x, long y, long z);
이제 이것을 사용해야 하는데, 이때 사용해야 하는 부분을 검색을 통해 알아 두었다. (C# 자체가 익숙치 않다)
우선 배열 형식의 선언을 한 뒤, 데이터를 담는다.
_GraphMarshal ocx = graphView.GetOcx() as _GraphMarshal;
int dataSize = 100000;
double[] x = new double[dataSize];
double[] y = new double[dataSize];
double[] z = new double[dataSize];
for (int i = 0; i < dataSize; i++)
{
x[i] = i;
y[i] = 100 * Math.Sin(i * 3.14 / 180);
z[i] = 0;
}
IntPtr를 이용하여 주소를 받아갈 수 있도록 해야 한다. AllocHZGLobal과 FreeHGlobal을 이용하면 된다.
이 형식은 IntPtr 포인터를 지원하는 언어와 포인터를 지원하지 않는 언어 간의 데이터를 참조하는 일반적인 수단으로 사용할 수 있습니다.
IntPtr을 이용하여 메모리의 주소를 넘겨줄 수 있다.
IntPtr xPtr = Marshal.AllocHGlobal(sizeof(double) * x.Length);
Marshal.Copy(x, 0, xPtr, x.Length);
IntPtr yPtr = Marshal.AllocHGlobal(sizeof(double) * y.Length);
Marshal.Copy(y, 0, yPtr, y.Length);
IntPtr zPtr = Marshal.AllocHGlobal(sizeof(double) * z.Length);
Marshal.Copy(z, 0, zPtr, z.Length);
ocx.AddArrayData("sine", dataSize, (long)xPtr, (long)yPtr, (long)zPtr);
Marshal.FreeHGlobal(xPtr);
Marshal.FreeHGlobal(yPtr);
Marshal.FreeHGlobal(zPtr);
728x90
반응형
'Program Language > C#' 카테고리의 다른 글
[C#] 구조체와 클래스 (0) | 2023.02.16 |
---|---|
[C#] abstract class (0) | 2023.02.16 |
[C#] C++로 만들어진 OCX 사용하기 (0) | 2022.10.26 |
[C#] C#에서 OCX를 사용할 때 LicenseException 에러 발생 (0) | 2022.10.26 |
[C#] C++ 구조체 사용하기 (2) | 2022.09.16 |